Esempio n. 1
0
static int sw_uart_request_port(struct uart_port *port)
{
	struct sw_uart_port *sw_uport = UART_TO_SPORT(port);
	int ret;

	SERIAL_DBG("request port(ioremap & request io) %d\n", port->line);
	/* request memory resource */
	if (!request_mem_region(port->mapbase, SUNXI_UART_MEM_RANGE, SUNXI_UART_DEV_NAME)) {
		SERIAL_MSG("uart%d, request mem region failed\n", sw_uport->id);
		return -EBUSY;
	}
	port->membase = ioremap(port->mapbase, SUNXI_UART_MEM_RANGE);
	if (!port->membase) {
		SERIAL_MSG("uart%d, ioremap failed\n", sw_uport->id);
		release_mem_region(port->mapbase, SUNXI_UART_MEM_RANGE);
		return -EBUSY;
	}

	/* request io resource */
	ret = sw_uart_request_gpio(sw_uport);
	if (ret < 0) {
		release_mem_region(port->mapbase, SUNXI_UART_MEM_RANGE);
		return ret;
	}

	return 0;
}
Esempio n. 2
0
static int sw_uart_request_resource(struct sw_uart_port* sw_uport, struct sw_uart_pdata *pdata)
{
	struct uart_port *port = &sw_uport->port;

	SERIAL_DBG("get system resource(clk & IO)\n");

	if (sw_uart_regulator_request(sw_uport, pdata) < 0) {
		SERIAL_MSG("uart%d request regulator failed!\n", sw_uport->id);
		return -ENXIO;
	}
	sw_uart_regulator_enable(pdata);

	sw_uport->mclk = clk_get(port->dev, sw_uport->name);
	if (IS_ERR_OR_NULL(sw_uport->mclk)) {
		SERIAL_MSG("uart%d get mclk failed\n", sw_uport->id);
		return PTR_ERR(sw_uport->mclk);
	}

	#ifdef CONFIG_SW_UART_DUMP_DATA
	sw_uport->dump_buff = (char*)kmalloc(MAX_DUMP_SIZE, GFP_KERNEL);
	if (!sw_uport->dump_buff) {
		SERIAL_MSG("uart%d fail to alloc dump buffer\n", sw_uport->id);
	}
	#endif

	return 0;
}
Esempio n. 3
0
    /**
     * Print calibration results for plotting or manual frame adjustment.
     */
    void Bed_level::print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, float (*fn)(const uint8_t, const uint8_t)) {

      #if DISABLED(SCAD_MESH_OUTPUT)
        SERIAL_STR(ECHO);
        for (uint8_t x = 0; x < sx; x++) {
          for (uint8_t i = 0; i < precision + 2 + (x < 10 ? 1 : 0); i++)
            SERIAL_CHR(' ');
          SERIAL_VAL((int)x);
        }
        SERIAL_EOL();
      #endif

      #if ENABLED(SCAD_MESH_OUTPUT)
        SERIAL_EM("measured_z = [");  // open 2D array
      #endif

      for (uint8_t y = 0; y < sy; y++) {
        #if ENABLED(SCAD_MESH_OUTPUT)
          SERIAL_MSG(" [");             // open sub-array
        #else
          SERIAL_STR(ECHO);
          if (y < 10) SERIAL_CHR(' ');
          SERIAL_VAL((int)y);
        #endif
        for (uint8_t x = 0; x < sx; x++) {
          SERIAL_CHR(' ');
          const float offset = fn(x, y);
          if (!isnan(offset)) {
            if (offset >= 0) SERIAL_CHR('+');
            SERIAL_VAL(offset, precision);
          }
          else {
            #if ENABLED(SCAD_MESH_OUTPUT)
              for (uint8_t i = 3; i < precision + 3; i++)
                SERIAL_CHR(' ');
              SERIAL_MSG("NAN");
            #else
              for (uint8_t i = 0; i < precision + 3; i++)
                SERIAL_CHR(i ? '=' : ' ');
            #endif
          }
          #if ENABLED(SCAD_MESH_OUTPUT)
            if (x < sx - 1) SERIAL_CHR(',');
          #endif
        }
        #if ENABLED(SCAD_MESH_OUTPUT)
          SERIAL_CHR(' ');
          SERIAL_CHR(']');                     // close sub-array
          if (y < sy - 1) SERIAL_CHR(',');
        #endif
        SERIAL_EOL();
      }

      #if ENABLED(SCAD_MESH_OUTPUT)
        SERIAL_MSG("\n];");                     // close 2D array
      #endif

      SERIAL_EOL();

    }
Esempio n. 4
0
static void sw_uart_pm(struct uart_port *port, unsigned int state,
		      unsigned int oldstate)
{
	struct sw_uart_port *sw_uport = UART_TO_SPORT(port);
	int ret;

	SERIAL_DBG("PM state %d -> %d\n", oldstate, state);

	switch (state) {
	case 0: /* Power up */
		if (sw_uport->mclk->enable_count > 0) {
			SERIAL_MSG("uart%d clk is already enable\n", sw_uport->id);
			break;
		}

		ret = clk_prepare_enable(sw_uport->mclk);
		if (ret) {
			SERIAL_MSG("uart%d release reset failed\n", sw_uport->id);
		}
		break;
	case 3: /* Power down */
		if (sw_uport->mclk->enable_count == 0) {
			SERIAL_MSG("uart%d clk is already disable\n", sw_uport->id);
			break;
		}

		clk_disable_unprepare(sw_uport->mclk);
		break;
	default:
		SERIAL_MSG("uart%d, Unknown PM state %d\n", sw_uport->id, state);
	}
}
Esempio n. 5
0
static int sw_uart_startup(struct uart_port *port)
{
	struct sw_uart_port *sw_uport = UART_TO_SPORT(port);
	int ret;

	SERIAL_DBG("start up ...\n");

	ret = request_irq(port->irq, sw_uart_irq, 0, sw_uport->name, port);
	if (unlikely(ret)) {
		SERIAL_MSG("uart%d cannot get irq %d\n", sw_uport->id, port->irq);
		return ret;
	}

	sw_uport->msr_saved_flags = 0;
	/*
	 * PTIME mode to select the THRE trigger condition:
	 * if PTIME=1(IER[7]), the THRE interrupt will be generated when the
	 * the water level of the TX FIFO is lower than the threshold of the
	 * TX FIFO. and if PTIME=0, the THRE interrupt will be generated when
	 * the TX FIFO is empty.
	 * In addition, when PTIME=1, the THRE bit of the LSR register will not
	 * be set when the THRE interrupt is generated. You must check the
	 * interrupt id of the IIR register to decide whether some data need to
	 * send.
	 */
	sw_uport->ier = SW_UART_IER_RLSI | SW_UART_IER_RDI;
	#ifdef CONFIG_SW_UART_PTIME_MODE
	sw_uport->ier |= SW_UART_IER_PTIME;
	#endif

	return 0;
}
Esempio n. 6
0
static int sw_uart_resume(struct device *dev)
{
#ifdef CONFIG_EVB_PLATFORM
	unsigned long flags = 0;
#endif
	struct uart_port *port = dev_get_drvdata(dev);
	struct sw_uart_port *sw_uport = UART_TO_SPORT(port);

	if (port) {
		if (SW_UART_NEED_SUSPEND(port)) {
			sw_uart_regulator_enable(dev->platform_data);
			sw_uart_select_gpio_state(sw_uport->pctrl, PINCTRL_STATE_DEFAULT, sw_uport->id);
		}
#ifdef CONFIG_EVB_PLATFORM
		/* It's used only in super-standby mode. 
		  FPGA maybe fall into sw_uart_force_lcr(), so comment it. */
		if (sw_is_console_port(port) && !console_suspend_enabled) {
			spin_lock_irqsave(&port->lock, flags);
			sw_uart_reset(sw_uport);
			serial_out(port, sw_uport->fcr, SW_UART_FCR);
			serial_out(port, sw_uport->mcr, SW_UART_MCR);
			serial_out(port, sw_uport->lcr|SW_UART_LCR_DLAB, SW_UART_LCR);
			serial_out(port, sw_uport->dll, SW_UART_DLL);
			serial_out(port, sw_uport->dlh, SW_UART_DLH);
			serial_out(port, sw_uport->lcr, SW_UART_LCR);
			serial_out(port, sw_uport->ier, SW_UART_IER);
			spin_unlock_irqrestore(&port->lock, flags);
		}
#endif
		uart_resume_port(&sw_uart_driver, port);
		SERIAL_MSG("uart%d resume. DLH: %d, DLL: %d. \n", port->line, sw_uport->dlh, sw_uport->dll);
	}

	return 0;
}
Esempio n. 7
0
static int __init sw_console_setup(struct console *co, char *options)
{
	struct uart_port *port = NULL;
	struct sw_uart_port *sw_uport;
	int baud = 115200;
	int bits = 8;
	int parity = 'n';
	int flow = 'n';

	if (unlikely(co->index >= SUNXI_UART_NUM || co->index < 0))
		return -ENXIO;

	port = sw_console_get_port(co);
	if (port == NULL)
		return -ENODEV;
	sw_uport = UART_TO_SPORT(port);
	if (!port->iobase && !port->membase)
		return -ENODEV;

	if (options)
		uart_parse_options(options, &baud, &parity, &bits, &flow);

	SERIAL_MSG("console setup baud %d parity %c bits %d, flow %c\n",
			baud, parity, bits, flow);
	return uart_set_options(port, co, baud, parity, bits, flow);
}
Esempio n. 8
0
static int __init sunxi_uart_init(void)
{
	int ret;
	u32 i;
	struct sw_uart_pdata *pdata;

	sunxi_uart_device_scan();
	ret = sw_uart_get_devinfo();
	if (unlikely(ret))
		return ret;

	ret = uart_register_driver(&sw_uart_driver);
	if (unlikely(ret)) {
		SERIAL_MSG("driver initializied\n");
		return ret;
	}

	for (i=0; i<SUNXI_UART_NUM; i++) {
		pdata = &sw_uport_pdata[i];
		if (!pdata->used)
			continue;
		platform_device_register(&sw_uport_device[i]);
		sunxi_uart_sysfs(&sw_uport_device[i]);
	}

	return platform_driver_register(&sw_uport_platform_driver);
}
Esempio n. 9
0
static inline int sw_uart_check_baudset(struct uart_port *port, unsigned int baud)
{
	struct sw_uart_port *sw_uport = UART_TO_SPORT(port);
	static struct baudset  baud_set[] = {
		{115200, 24000000, 120000000},
		{230400, 30000000, 120000000},
		{380400, 24000000, 120000000},
		{460800, 30000000, 120000000},
		{921600, 30000000, 120000000},
		{1000000, 31000000, 120000000}, //31578947
		{1500000, 24000000, 120000000},
		{1750000, 54000000, 120000000}, //54545454
		{2000000, 31000000, 120000000}, //31578947
		{2500000, 40000000, 120000000}, //40000000
		{3000000, 46000000, 120000000}, //46153846
		{3250000, 54000000, 120000000}, //54545454
		{3500000, 54000000, 120000000}, //54545454
		{4000000, 66000000, 120000000}, //66666666
	};
	struct baudset *setsel;
	int i;

	if (baud < 115200) {
		if (port->uartclk < 24000000) {
			SERIAL_MSG("uart%d, uartclk(%d) too small for baud %d\n",
				sw_uport->id, port->uartclk, baud);
			return -1;
		}
	} else {
		for (i=0;
		     i<sizeof(baud_set)/sizeof(baud_set[0]) && baud != baud_set[i].baud;
		     i++);
		if (i==sizeof(baud_set)/sizeof(baud_set[0])) {
			SERIAL_MSG("uart%d, baud %d beyond rance\n", sw_uport->id, baud);
			return -1;
		}
		setsel = &baud_set[i];
		if (port->uartclk < setsel->uartclk_min
			|| port->uartclk > setsel->uartclk_max) {
			SERIAL_MSG("uart%d, select set %d, baud %d, uartclk %d beyond rance[%d, %d]\n",
				sw_uport->id, i, baud, port->uartclk,
				setsel->uartclk_min, setsel->uartclk_max);
			return -1;
		}
	}
	return 0;
}
Esempio n. 10
0
static int sw_uart_select_gpio_state(struct pinctrl *pctrl, char *name, u32 no)
{
	int ret = 0;
	struct pinctrl_state *pctrl_state = NULL;
	
	pctrl_state = pinctrl_lookup_state(pctrl, name);
	if (IS_ERR(pctrl_state)) {
		SERIAL_MSG("UART%d pinctrl_lookup_state(%s) failed! return %p \n", no, name, pctrl_state);
		return -1;
	}

	ret = pinctrl_select_state(pctrl, pctrl_state);
	if (ret < 0)
		SERIAL_MSG("UART%d pinctrl_select_state(%s) failed! return %d \n", no, name, ret);

	return ret;
}
Esempio n. 11
0
static void __exit sunxi_uart_exit(void)
{
	SERIAL_MSG("driver exit\n");
#ifdef CONFIG_SERIAL_SUNXI_CONSOLE
	unregister_console(&sw_console);
#endif
	platform_driver_unregister(&sw_uport_platform_driver);
	uart_unregister_driver(&sw_uart_driver);
}
Esempio n. 12
0
static int __devinit sw_uart_probe(struct platform_device *pdev)
{
	struct uart_port *port;
	struct sw_uart_port *sw_uport;
	int ret = -1;

	port = &sw_uart_ports[pdev->id].port;
	port->dev = &pdev->dev;
	sw_uport = UART_TO_SPORT(port);
	sw_uport->id = pdev->id;
	sw_uport->ier = 0;
	sw_uport->lcr = 0;
	sw_uport->mcr = 0;
	sw_uport->fcr = 0;
	sw_uport->dll = 0;
	sw_uport->dlh = 0;
	snprintf(sw_uport->name, 16, SUNXI_UART_DEV_NAME"%d", pdev->id);
	pdev->dev.init_name = sw_uport->name;

	SERIAL_DBG("uart.%d probe ... \n", pdev->id);

	/* request system resource and init them */
	ret = sw_uart_request_resource(sw_uport, pdev->dev.platform_data);
	if (unlikely(ret)) {
		SERIAL_MSG("uart%d error to get resource\n", pdev->id);
		return -ENXIO;
	}

	port->uartclk = clk_get_rate(sw_uport->mclk);

	/* bug: clk_get_rate can't get s_uart clk rate in real-time,
		 so set it to actual value */
#ifdef SUNXI_S_UART
#ifdef CONFIG_ARCH_SUN8IW5P1
	if (pdev->id == (SUNXI_UART_NUM - 1))
		port->uartclk = 200000000;
#endif
#endif

	port->type = PORT_SUNXI;
	port->flags = UPF_BOOT_AUTOCONF;
	port->mapbase = sw_uport->pdata->base;
	port->irq = sw_uport->pdata->irq;
	port->line = sw_uport->pdata->port_no;
	platform_set_drvdata(pdev, port);

	SERIAL_DBG("add uart%d port, port_type %d, uartclk %d\n",
			pdev->id, port->type, port->uartclk);
	return uart_add_one_port(&sw_uart_driver, port);
}
Esempio n. 13
0
static int sw_uart_regulator_request(struct sw_uart_port* sw_uport, struct sw_uart_pdata *pdata)
{
	struct regulator *regu = NULL;

	/* Consider "n***" as nocare. Support "none", "nocare", "null", "" etc. */
	if ((pdata->regulator_id[0] == 'n') || (pdata->regulator_id[0] == 0))
		return 0;

	regu = regulator_get(NULL, pdata->regulator_id);
	if (IS_ERR(regu)) {
		SERIAL_MSG("get regulator %s failed!\n", pdata->regulator_id);
		return -1;
	}
	pdata->regulator = regu;
	return 0;
}
Esempio n. 14
0
static int sw_uart_suspend(struct device *dev)
{
	struct uart_port *port = dev_get_drvdata(dev);
	struct sw_uart_port *sw_uport = UART_TO_SPORT(port);

	if (port) {
		SERIAL_MSG("uart%d suspend\n", port->line);
		uart_suspend_port(&sw_uart_driver, port);

		if (SW_UART_NEED_SUSPEND(port)) {
			sw_uart_select_gpio_state(sw_uport->pctrl, PINCTRL_STATE_SUSPEND, sw_uport->id);
			sw_uart_regulator_disable(dev->platform_data);
		}
	}

	return 0;
}
Esempio n. 15
0
    /**
     * Extrapolate a single point from its neighbors
     */
    void Bed_level::extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir) {
      #if ENABLED(DEBUG_LEVELING_FEATURE)
        if (DEBUGGING(LEVELING)) {
          SERIAL_MSG("Extrapolate [");
          if (x < 10) SERIAL_CHR(' ');
          SERIAL_VAL((int)x);
          SERIAL_CHR(xdir ? (xdir > 0 ? '+' : '-') : ' ');
          SERIAL_CHR(' ');
          if (y < 10) SERIAL_CHR(' ');
          SERIAL_VAL((int)y);
          SERIAL_CHR(ydir ? (ydir > 0 ? '+' : '-') : ' ');
          SERIAL_CHR(']');
        }
      #endif
      if (!isnan(z_values[x][y])) {
        #if ENABLED(DEBUG_LEVELING_FEATURE)
          if (DEBUGGING(LEVELING)) SERIAL_EM(" (done)");
        #endif
        return;  // Don't overwrite good values.
      }
      SERIAL_EOL();

      // Get X neighbors, Y neighbors, and XY neighbors
      const uint8_t x1 = x + xdir, y1 = y + ydir, x2 = x1 + xdir, y2 = y1 + ydir;
      float a1 = z_values[x1][y ], a2 = z_values[x2][y ],
            b1 = z_values[x ][y1], b2 = z_values[x ][y2],
            c1 = z_values[x1][y1], c2 = z_values[x2][y2];

      // Treat far unprobed points as zero, near as equal to far
      if (isnan(a2)) a2 = 0.0; if (isnan(a1)) a1 = a2;
      if (isnan(b2)) b2 = 0.0; if (isnan(b1)) b1 = b2;
      if (isnan(c2)) c2 = 0.0; if (isnan(c1)) c1 = c2;

      const float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2;

      // Take the average instead of the median
      z_values[x][y] = (a + b + c) / 3.0;

      // Median is robust (ignores outliers).
      // z_values[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c)
      //                                : ((c < b) ? b : (a < c) ? a : c);
    }
Esempio n. 16
0
 void GCodeParser::debug() {
   SERIAL_MV("Command: ", command_ptr);
   SERIAL_MV(" (", command_letter);
   SERIAL_VAL(codenum);
   SERIAL_EM(")");
   #if ENABLED(FASTER_GCODE_PARSER)
     SERIAL_MSG(" args: \"");
     for (char c = 'A'; c <= 'Z'; ++c)
       if (seen(c)) { SERIAL_CHR(c); SERIAL_CHR(' '); }
   #else
     SERIAL_MV(" args: \"", command_args);
   #endif
   SERIAL_MSG("\"");
   if (string_arg) {
     SERIAL_MSG(" string: \"");
     SERIAL_TXT(string_arg);
     SERIAL_CHR('"');
   }
   SERIAL_MSG("\n\n");
   for (char c = 'A'; c <= 'Z'; ++c) {
     if (seen(c)) {
       SERIAL_MV("Code '", c); SERIAL_MSG("':");
       if (has_value()) {
         SERIAL_MV("\n    float: ", value_float());
         SERIAL_MV("\n     long: ", value_long());
         SERIAL_MV("\n    ulong: ", value_ulong());
         SERIAL_MV("\n   millis: ", value_millis());
         SERIAL_MV("\n   sec-ms: ", value_millis_from_seconds());
         SERIAL_MV("\n      int: ", value_int());
         SERIAL_MV("\n   ushort: ", value_ushort());
         SERIAL_MV("\n     byte: ", (int)value_byte());
         SERIAL_MV("\n     bool: ", (int)value_bool());
         SERIAL_MV("\n   linear: ", value_linear_units());
         SERIAL_MV("\n  celsius: ", value_celsius());
       }
       else
         SERIAL_MSG(" (no value)");
       SERIAL_MSG("\n\n");
     }
   }
 }
Esempio n. 17
0
static int sw_uart_request_gpio(struct sw_uart_port *sw_uport)
{
#ifdef SUNXI_S_UART
	if (sw_uport->id == (SUNXI_UART_NUM - 1)) {
		/* use name s_uart0 to get pinctrl */
		snprintf(sw_uport->name, 16, SUNXI_S_UART_DEV_NAME"%d", 0);
	}
#endif

	sw_uport->pctrl = devm_pinctrl_get(sw_uport->port.dev);

#ifdef SUNXI_S_UART
	if (sw_uport->id == (SUNXI_UART_NUM - 1)) {
		snprintf(sw_uport->name, 16, SUNXI_UART_DEV_NAME"%d", sw_uport->id);
	}
#endif

	if (IS_ERR_OR_NULL(sw_uport->pctrl)) {
		SERIAL_MSG("UART%d devm_pinctrl_get() failed! return %ld\n", sw_uport->id, PTR_ERR(sw_uport->pctrl));
		return -1;
	}

	return sw_uart_select_gpio_state(sw_uport->pctrl, PINCTRL_STATE_DEFAULT, sw_uport->id);
}
Esempio n. 18
0
static int sw_uart_get_devinfo(void)
{
	u32 i;
	char uart_para[16] = {0};
	struct sw_uart_pdata *pdata = NULL;
	script_item_u val = {0};
	script_item_value_type_e type = 0;

	for (i=0; i<SUNXI_UART_NUM; i++) {
		pdata = &sw_uport_pdata[i];
		sprintf(uart_para, SUNXI_UART_DEV_NAME"%d", i);
		/* get used information */
		type = script_get_item(uart_para, "uart_used", &val);
		if (type != SCIRPT_ITEM_VALUE_TYPE_INT) {
			SERIAL_MSG("get uart%d's usedcfg failed\n", i);
			continue;
		}
		pdata->used = val.val;
		if (pdata->used == 0)
			continue;

		/* get type information */
		type = script_get_item(uart_para, "uart_type", &val);
		if (type != SCIRPT_ITEM_VALUE_TYPE_INT) {
			SERIAL_MSG("get uart%d's type failed\n", i);
			return -1;
		}
		if (val.val > pdata->max_ios) {
			SERIAL_MSG("io type error: (%d > max_io_num %d)\n", val.val, pdata->max_ios);
			return -1;
		}
		pdata->io_num = val.val;

		/* get port information */
		type = script_get_item(uart_para, "uart_port", &val);
		if (type != SCIRPT_ITEM_VALUE_TYPE_INT) {
			//SERIAL_MSG("get uart%d's port failed\n", i);
			pdata->port_no = i;
		}
		else
			pdata->port_no = val.val;

		type = script_get_item(uart_para, "uart_regulator", &val);
		if (SCIRPT_ITEM_VALUE_TYPE_STR != type) {
			SERIAL_MSG("uart%d has no uart_regulator.\n", i);
			continue;
		}
		strncpy(pdata->regulator_id, val.str, 16);

	}

#ifdef SUNXI_S_UART
	do {
		pdata = &sw_uport_pdata[SUNXI_UART_NUM - 1];
		sprintf(uart_para, SUNXI_S_UART_DEV_NAME"%d", 0);
		/* get used information */
		type = script_get_item(uart_para, "s_uart_used", &val);
		if (type != SCIRPT_ITEM_VALUE_TYPE_INT) {
			SERIAL_MSG("get s_uart0 usedcfg failed\n");
			continue;
		}
		if (val.val == 2)
			pdata->used = 1;

		pdata->io_num = gs_uart_io_num[SUNXI_UART_NUM - 1];

	} while(0);
#endif

	return 0;
}
Esempio n. 19
0
static void sw_uart_set_termios(struct uart_port *port, struct ktermios *termios,
			    struct ktermios *old)
{
	struct sw_uart_port *sw_uport = UART_TO_SPORT(port);
	unsigned long flags;
	unsigned int baud, quot, lcr = 0, dll, dlh;
	unsigned int lcr_fail = 0;

	SERIAL_DBG("set termios ...\n");
	switch (termios->c_cflag & CSIZE) {
	case CS5:
		lcr |= SW_UART_LCR_WLEN5;
		break;
	case CS6:
		lcr |= SW_UART_LCR_WLEN6;
		break;
	case CS7:
		lcr |= SW_UART_LCR_WLEN7;
		break;
	case CS8:
	default:
		lcr |= SW_UART_LCR_WLEN8;
		break;
	}

	if (termios->c_cflag & CSTOPB)
		lcr |= SW_UART_LCR_STOP;
	if (termios->c_cflag & PARENB)
		lcr |= SW_UART_LCR_PARITY;
	if (!(termios->c_cflag & PARODD))
		lcr |= SW_UART_LCR_EPAR;

	/* set buadrate */
	baud = uart_get_baud_rate(port, termios, old,
				  port->uartclk / 16 / 0xffff,
				  port->uartclk / 16);
	sw_uart_check_baudset(port, baud);
	quot = uart_get_divisor(port, baud);
	dll = quot & 0xff;
	dlh = quot >> 8;
	SERIAL_DBG("set baudrate %d, quot %d\n", baud, quot);

	spin_lock_irqsave(&port->lock, flags);
	uart_update_timeout(port, termios->c_cflag, baud);

	/* Update the per-port timeout. */
	port->read_status_mask = SW_UART_LSR_OE | SW_UART_LSR_THRE | SW_UART_LSR_DR;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= SW_UART_LSR_FE | SW_UART_LSR_PE;
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= SW_UART_LSR_BI;

	/* Characteres to ignore */
	port->ignore_status_mask = 0;
	if (termios->c_iflag & IGNPAR)
		port->ignore_status_mask |= SW_UART_LSR_PE | SW_UART_LSR_FE;
	if (termios->c_iflag & IGNBRK) {
		port->ignore_status_mask |= SW_UART_LSR_BI;
		/*
		 * If we're ignoring parity and break indicators,
		 * ignore overruns too (for real raw support).
		 */
		if (termios->c_iflag & IGNPAR)
			port->ignore_status_mask |= SW_UART_LSR_OE;
	}

	/*
	 * ignore all characters if CREAD is not set
	 */
	if ((termios->c_cflag & CREAD) == 0)
		port->ignore_status_mask |= SW_UART_LSR_DR;

	/*
	 * if lcr & baud are changed, reset controller to disable transfer
	 */
	if (lcr != sw_uport->lcr || dll != sw_uport->dll || dlh != sw_uport->dlh) {
//		SERIAL_DBG("LCR & BAUD changed, reset controller...\n");
		sw_uart_reset(sw_uport);
	}
	sw_uport->dll = dll;
	sw_uport->dlh = dlh;

	/* flow control */
	sw_uport->mcr &= ~SW_UART_MCR_AFE;
	if (termios->c_cflag & CRTSCTS)
		sw_uport->mcr |= SW_UART_MCR_AFE;
	serial_out(port, sw_uport->mcr, SW_UART_MCR);

	/*
	 * CTS flow control flag and modem status interrupts
	 */
	sw_uport->ier &= ~SW_UART_IER_MSI;
	if (UART_ENABLE_MS(port, termios->c_cflag))
		sw_uport->ier |= SW_UART_IER_MSI;
	serial_out(port, sw_uport->ier, SW_UART_IER);

	sw_uport->fcr = SW_UART_FCR_RXTRG_1_2 | SW_UART_FCR_TXTRG_1_2
			| SW_UART_FCR_FIFO_EN;
	serial_out(port, sw_uport->fcr, SW_UART_FCR);

	sw_uport->lcr = lcr;
	serial_out(port, sw_uport->lcr|SW_UART_LCR_DLAB, SW_UART_LCR);
	if (serial_in(port, SW_UART_LCR) != (sw_uport->lcr|SW_UART_LCR_DLAB)) {
		lcr_fail = 1;
	} else {
		sw_uport->lcr = lcr;
		serial_out(port, sw_uport->dll, SW_UART_DLL);
		serial_out(port, sw_uport->dlh, SW_UART_DLH);
		serial_out(port, sw_uport->lcr, SW_UART_LCR);
		if (serial_in(port, SW_UART_LCR) != sw_uport->lcr) {
			lcr_fail = 2;
		}
	}

	#ifdef CONFIG_SW_UART_FORCE_LCR
	if (lcr_fail) {
		sw_uart_force_lcr(sw_uport, 50);
		serial_in(port, SW_UART_USR);
	}
	#endif
	/* clear rxfifo after set lcr & baud to discard redundant data */
	serial_out(port, sw_uport->fcr|SW_UART_FCR_RXFIFO_RST, SW_UART_FCR);
	port->ops->set_mctrl(port, port->mctrl);

	/* Must save the current config for the resume of console(no tty user). */
	if (sw_is_console_port(port))
		port->cons->cflag = termios->c_cflag;

	spin_unlock_irqrestore(&port->lock, flags);
	/* lately output force lcr information */
	if (lcr_fail == 1) {
		SERIAL_MSG("uart%d write LCR(pre-dlab) failed, lcr %x reg %x\n",
			sw_uport->id, sw_uport->lcr|(u32)SW_UART_LCR_DLAB,
			serial_in(port, SW_UART_LCR));
	} else if (lcr_fail == 2) {
		SERIAL_MSG("uart%d write LCR(post-dlab) failed, lcr %x reg %x\n",
			sw_uport->id, sw_uport->lcr, serial_in(port, SW_UART_LCR));
	}
	/* Don't rewrite B0 */
	if (tty_termios_baud_rate(termios))
		tty_termios_encode_baud_rate(termios, baud, baud);
	SERIAL_DBG("termios lcr 0x%x fcr 0x%x mcr 0x%x dll 0x%x dlh 0x%x\n",
			sw_uport->lcr, sw_uport->fcr, sw_uport->mcr,
			sw_uport->dll, sw_uport->dlh);
}
Esempio n. 20
0
// Populate all fields by parsing a single line of GCode
// 58 bytes of SRAM are used to speed up seen/value
void GCodeParser::parse(char *p) {

  reset(); // No codes to report

  // Skip spaces
  while (*p == ' ') ++p;

  // Skip N[-0-9] if included in the command line
  if (*p == 'N' && NUMERIC_SIGNED(p[1])) {
    #if ENABLED(FASTER_GCODE_PARSER)
      //set('N', p + 1);     // (optional) Set the 'N' parameter value
    #endif
    p += 2;                  // skip N[-0-9]
    while (NUMERIC(*p)) ++p; // skip [0-9]*
    while (*p == ' ')   ++p; // skip [ ]*
  }

  // *p now points to the current command, which should be G, M, or T
  command_ptr = p;

  // Get the command letter, which must be G, M, or T
  const char letter = *p++;

  // Nullify asterisk and trailing whitespace
  char *starpos = strchr(p, '*');
  if (starpos) {
    --starpos;                          // *
    while (*starpos == ' ') --starpos;  // spaces...
    starpos[1] = '\0';
  }

  // Bail if the letter is not G, M, or T
  switch (letter) { case 'G': case 'M': case 'T': break; default: return; }

  // Skip spaces to get the numeric part
  while (*p == ' ') p++;

  // Bail if there's no command code number
  if (!NUMERIC(*p)) return;

  // Save the command letter at this point
  // A '?' signifies an unknown command
  command_letter = letter;

  // Get the code number - integer digits only
  codenum = 0;
  do {
    codenum *= 10, codenum += *p++ - '0';
  } while (NUMERIC(*p));

  // Allow for decimal point in command
  #if USE_GCODE_SUBCODES
    if (*p == '.') {
      p++;
      while (NUMERIC(*p))
        subcode *= 10, subcode += *p++ - '0';
    }
  #endif

  // Skip all spaces to get to the first argument, or nul
  while (*p == ' ') p++;

  // The command parameters (if any) start here, for sure!

  #if DISABLED(FASTER_GCODE_PARSER)
    command_args = p; // Scan for parameters in seen()
  #endif

  // Only use string_arg for these M codes
  if (letter == 'M') switch (codenum) { case 23: case 28: case 30: case 117: case 118: case 928: string_arg = p; return; default: break; }

  #if ENABLED(DEBUG_GCODE_PARSER)
    const bool debug = codenum == 800;
  #endif

  /**
   * Find all parameters, set flags and pointers for fast parsing
   *
   * Most codes ignore 'string_arg', but those that want a string will get the right pointer.
   * The following loop assigns the first "parameter" having no numeric value to 'string_arg'.
   * This allows M0/M1 with expire time to work: "M0 S5 You Win!"
   */
  string_arg = NULL;
  while (char code = *p++) {                    // Get the next parameter. A NUL ends the loop

    // Special handling for M32 [P] !/path/to/file.g#
    // The path must be the last parameter
    if (code == '!' && letter == 'M' && codenum == 32) {
      string_arg = p;                           // Name starts after '!'
      char * const lb = strchr(p, '#');         // Already seen '#' as SD char (to pause buffering)
      if (lb) *lb = '\0';                       // Safe to mark the end of the filename
      return;
    }

    // Arguments MUST be uppercase for fast GCode parsing
    #if ENABLED(FASTER_GCODE_PARSER)
      #define PARAM_TEST WITHIN(code, 'A', 'Z')
    #else
      #define PARAM_TEST true
    #endif

    if (PARAM_TEST) {

      while (*p == ' ') p++;                    // skip spaces between parameters & values
      const bool has_num = DECIMAL_SIGNED(*p);  // The parameter has a number [-+0-9.]

      #if ENABLED(DEBUG_GCODE_PARSER)
        if (debug) {
          SERIAL_MV("Got letter ", code); // DEBUG
          SERIAL_MV(" at index ", (int)(p - command_ptr - 1)); // DEBUG
          if (has_num) SERIAL_MSG(" (has_num)");
        }
      #endif

      if (!has_num && !string_arg) {            // No value? First time, keep as string_arg
        string_arg = p - 1;
        #if ENABLED(DEBUG_GCODE_PARSER)
          if (debug) SERIAL_MV(" string_arg: ", hex_address((void*)string_arg)); // DEBUG
        #endif
      }

      #if ENABLED(DEBUG_GCODE_PARSER)
        if (debug) SERIAL_EOL();
      #endif

      #if ENABLED(FASTER_GCODE_PARSER)
        set(code, has_num ? p : NULL            // Set parameter exists and pointer (NULL for no number)
          #if ENABLED(DEBUG_GCODE_PARSER)
            , debug
          #endif
        );
      #endif
    }
    else if (!string_arg) {                     // Not A-Z? First time, keep as the string_arg
      string_arg = p - 1;
      #if ENABLED(DEBUG_GCODE_PARSER)
        if (debug) SERIAL_MV(" string_arg: ", hex_address((void*)string_arg)); // DEBUG
      #endif
    }

    if (!WITHIN(*p, 'A', 'Z')) {
      while (*p && NUMERIC(*p)) p++;            // Skip over the value section of a parameter
      while (*p == ' ') p++;                    // Skip over all spaces
    }
  }
}