Example #1
0
static int wm8961_i2c_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	struct wm8961_priv *wm8961;
	unsigned int val;
	int ret;

	wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv),
			      GFP_KERNEL);
	if (wm8961 == NULL)
		return -ENOMEM;

	wm8961->regmap = devm_regmap_init_i2c(i2c, &wm8961_regmap);
	if (IS_ERR(wm8961->regmap))
		return PTR_ERR(wm8961->regmap);

	ret = regmap_read(wm8961->regmap, WM8961_SOFTWARE_RESET, &val);
	if (ret != 0) {
		dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
		return ret;
	}

	if (val != 0x1801) {
		dev_err(&i2c->dev, "Device is not a WM8961: ID=0x%x\n", val);
		return -EINVAL;
	}

	/* This isn't volatile - readback doesn't correspond to write */
	regcache_cache_bypass(wm8961->regmap, true);
	ret = regmap_read(wm8961->regmap, WM8961_RIGHT_INPUT_VOLUME, &val);
	regcache_cache_bypass(wm8961->regmap, false);

	if (ret != 0) {
		dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret);
		return ret;
	}

	dev_info(&i2c->dev, "WM8961 family %d revision %c\n",
		 (val & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
		 ((val & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
		 + 'A');

	ret = regmap_write(wm8961->regmap, WM8961_SOFTWARE_RESET, 0x1801);
	if (ret != 0) {
		dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
		return ret;
	}

	i2c_set_clientdata(i2c, wm8961);

	ret = snd_soc_register_codec(&i2c->dev,
			&soc_codec_dev_wm8961, &wm8961_dai, 1);

	return ret;
}
Example #2
0
static int sc16is7xx_startup(struct uart_port *port)
{
	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
	unsigned int val;

	sc16is7xx_power(port, 1);

	/* Reset FIFOs*/
	val = SC16IS7XX_FCR_RXRESET_BIT | SC16IS7XX_FCR_TXRESET_BIT;
	sc16is7xx_port_write(port, SC16IS7XX_FCR_REG, val);
	udelay(5);
	sc16is7xx_port_write(port, SC16IS7XX_FCR_REG,
			     SC16IS7XX_FCR_FIFO_BIT);

	/* Enable EFR */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
			     SC16IS7XX_LCR_CONF_MODE_B);

	regcache_cache_bypass(s->regmap, true);

	/* Enable write access to enhanced features and internal clock div */
	sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
			     SC16IS7XX_EFR_ENABLE_BIT);

	/* Enable TCR/TLR */
	sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
			      SC16IS7XX_MCR_TCRTLR_BIT,
			      SC16IS7XX_MCR_TCRTLR_BIT);

	/* Configure flow control levels */
	/* Flow control halt level 48, resume level 24 */
	sc16is7xx_port_write(port, SC16IS7XX_TCR_REG,
			     SC16IS7XX_TCR_RX_RESUME(24) |
			     SC16IS7XX_TCR_RX_HALT(48));

	regcache_cache_bypass(s->regmap, false);

	/* Now, initialize the UART */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);

	/* Enable the Rx and Tx FIFO */
	sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
			      SC16IS7XX_EFCR_RXDISABLE_BIT |
			      SC16IS7XX_EFCR_TXDISABLE_BIT,
			      0);

	/* Enable RX, TX, CTS change interrupts */
	val = SC16IS7XX_IER_RDI_BIT | SC16IS7XX_IER_THRI_BIT |
	      SC16IS7XX_IER_CTSI_BIT;
	sc16is7xx_port_write(port, SC16IS7XX_IER_REG, val);

	return 0;
}
Example #3
0
static int sc16is7xx_set_baud(struct uart_port *port, int baud)
{
	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
	u8 lcr;
	u8 prescaler = 0;
	unsigned long clk = port->uartclk, div = clk / 16 / baud;

	if (div > 0xffff) {
		prescaler = SC16IS7XX_MCR_CLKSEL_BIT;
		div /= 4;
	}

	lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);

	/* Open the LCR divisors for configuration */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
			     SC16IS7XX_LCR_CONF_MODE_B);

	/* Enable enhanced features */
	regcache_cache_bypass(s->regmap, true);
	sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
			     SC16IS7XX_EFR_ENABLE_BIT);
	regcache_cache_bypass(s->regmap, false);

	/* Put LCR back to the normal mode */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);

	sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
			      SC16IS7XX_MCR_CLKSEL_BIT,
			      prescaler);

	/* Open the LCR divisors for configuration */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
			     SC16IS7XX_LCR_CONF_MODE_A);

	/* Write the new divisor */
	regcache_cache_bypass(s->regmap, true);
	sc16is7xx_port_write(port, SC16IS7XX_DLH_REG, div / 256);
	sc16is7xx_port_write(port, SC16IS7XX_DLL_REG, div % 256);
	regcache_cache_bypass(s->regmap, false);

	/* Put LCR back to the normal mode */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);

	return DIV_ROUND_CLOSEST(clk / 16, div);
}
Example #4
0
static int adau1977_reset(struct adau1977 *adau1977)
{
	int ret;

	/*
	 * The reset bit is obviously volatile, but we need to be able to cache
	 * the other bits in the register, so we can't just mark the whole
	 * register as volatile. Since this is the only place where we'll ever
	 * touch the reset bit just bypass the cache for this operation.
	 */
	regcache_cache_bypass(adau1977->regmap, true);
	ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER,
			ADAU1977_POWER_RESET);
	regcache_cache_bypass(adau1977->regmap, false);
	if (ret)
		return ret;

	return ret;
}
Example #5
0
/**
 * twl_regcache_bypass - Configure the regcache bypass for the regmap associated
 *			 with the module
 * @mod_no: module number
 * @enable: Regcache bypass state
 *
 * Returns 0 else failure.
 */
int twl_set_regcache_bypass(u8 mod_no, bool enable)
{
	struct regmap *regmap = twl_get_regmap(mod_no);

	if (!regmap)
		return -EPERM;

	regcache_cache_bypass(regmap, enable);

	return 0;
}
Example #6
0
/* work around ESD issue where sta32x resets and loses all configuration */
static void sta32x_watchdog(struct work_struct *work)
{
	struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
						  watchdog_work.work);
	struct snd_soc_codec *codec = sta32x->codec;
	unsigned int confa, confa_cached;

	/* check if sta32x has reset itself */
	confa_cached = snd_soc_read(codec, STA32X_CONFA);
	regcache_cache_bypass(sta32x->regmap, true);
	confa = snd_soc_read(codec, STA32X_CONFA);
	regcache_cache_bypass(sta32x->regmap, false);
	if (confa != confa_cached) {
		regcache_mark_dirty(sta32x->regmap);
		sta32x_cache_sync(codec);
	}

	if (!sta32x->shutdown)
		schedule_delayed_work(&sta32x->watchdog_work,
				      round_jiffies_relative(HZ));
}
Example #7
0
static void sc16is7xx_handle_tx(struct uart_port *port)
{
	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
	struct circ_buf *xmit = &port->state->xmit;
	unsigned int txlen, to_send, i;

	if (unlikely(port->x_char)) {
		sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
		port->icount.tx++;
		port->x_char = 0;
		return;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
		return;

	/* Get length of data pending in circular buffer */
	to_send = uart_circ_chars_pending(xmit);
	if (likely(to_send)) {
		/* Limit to size of TX FIFO */
		txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG);
		to_send = (to_send > txlen) ? txlen : to_send;

		/* Add data to send */
		port->icount.tx += to_send;

		/* Convert to linear buffer */
		for (i = 0; i < to_send; ++i) {
			s->buf[i] = xmit->buf[xmit->tail];
			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		}
		regcache_cache_bypass(s->regmap, true);
		regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, s->buf, to_send);
		regcache_cache_bypass(s->regmap, false);
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
}
Example #8
0
static int max97236_i2c_probe(struct i2c_client *i2c,
				 const struct i2c_device_id *id)
{
	struct max97236_priv *max97236;
	int ret;

	max97236 = kzalloc(sizeof(struct max97236_priv), GFP_KERNEL);
	if (max97236 == NULL)
		return -ENOMEM;

	max97236->devtype = id->driver_data;
	i2c_set_clientdata(i2c, max97236);
	max97236->control_data = i2c;
	max97236->pdata = i2c->dev.platform_data;

	if (!max97236->pdata && i2c->dev.of_node)
		max97236->pdata = max97236_of_pdata(i2c);

	max97236->regmap = regmap_init_i2c(i2c, &max97236_regmap);
	if (IS_ERR(max97236->regmap)) {
		ret = PTR_ERR(max97236->regmap);
		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
		goto err_enable;
	}

	regcache_cache_bypass(max97236->regmap, false);

	ret = snd_soc_register_codec(&i2c->dev,
			&soc_codec_dev_max97236, max97236_dai,
			ARRAY_SIZE(max97236_dai));

	if (ret < 0)
		regmap_exit(max97236->regmap);

err_enable:
	return ret;
}
Example #9
0
static int adau1977_power_enable(struct adau1977 *adau1977)
{
	unsigned int val;
	int ret = 0;

	if (adau1977->enabled)
		return 0;

	ret = regulator_enable(adau1977->avdd_reg);
	if (ret)
		return ret;

	if (adau1977->dvdd_reg) {
		ret = regulator_enable(adau1977->dvdd_reg);
		if (ret)
			goto err_disable_avdd;
	}

	if (adau1977->reset_gpio)
		gpiod_set_value_cansleep(adau1977->reset_gpio, 1);

	regcache_cache_only(adau1977->regmap, false);

	if (adau1977->switch_mode)
		adau1977->switch_mode(adau1977->dev);

	ret = adau1977_reset(adau1977);
	if (ret)
		goto err_disable_dvdd;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER,
		ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP);
	if (ret)
		goto err_disable_dvdd;

	ret = regcache_sync(adau1977->regmap);
	if (ret)
		goto err_disable_dvdd;

	/*
	 * The PLL register is not affected by the software reset. It is
	 * possible that the value of the register was changed to the
	 * default value while we were in cache only mode. In this case
	 * regcache_sync will skip over it and we have to manually sync
	 * it.
	 */
	ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val);
	if (ret)
		goto err_disable_dvdd;

	if (val == 0x41) {
		regcache_cache_bypass(adau1977->regmap, true);
		ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL,
			0x41);
		if (ret)
			goto err_disable_dvdd;
		regcache_cache_bypass(adau1977->regmap, false);
	}

	adau1977->enabled = true;

	return ret;

err_disable_dvdd:
	if (adau1977->dvdd_reg)
		regulator_disable(adau1977->dvdd_reg);
err_disable_avdd:
		regulator_disable(adau1977->avdd_reg);
	return ret;
}
Example #10
0
static int arizona_apply_hardware_patch(struct arizona* arizona)
{
	unsigned int fll, sysclk;
	int ret, err;

	regcache_cache_bypass(arizona->regmap, true);

	/* Cache existing FLL and SYSCLK settings */
	ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll);
	if (ret != 0) {
		dev_err(arizona->dev, "Failed to cache FLL settings: %d\n",
			ret);
		return ret;
	}

	ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &sysclk);
	if (ret != 0) {
		dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n",
			ret);
		return ret;
	}

	/* Start up SYSCLK using the FLL in free running mode */
	ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1,
			ARIZONA_FLL1_ENA | ARIZONA_FLL1_FREERUN);
	if (ret != 0) {
		dev_err(arizona->dev,
			"Failed to start FLL in freerunning mode: %d\n",
			ret);
		return ret;
	}

	ret = arizona_poll_reg(arizona, 25, ARIZONA_INTERRUPT_RAW_STATUS_5,
			       ARIZONA_FLL1_CLOCK_OK_STS,
			       ARIZONA_FLL1_CLOCK_OK_STS);
	if (ret != 0) {
		dump_stack();
		ret = -ETIMEDOUT;
		goto err_fll;
	}

	ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, 0x0144);
	if (ret != 0) {
		dev_err(arizona->dev, "Failed to start SYSCLK: %d\n", ret);
		goto err_fll;
	}

	/* Start the write sequencer and wait for it to finish */
	ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
			ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
	if (ret != 0) {
		dev_err(arizona->dev, "Failed to start write sequencer: %d\n", ret);
		goto err_sysclk;
	}

	ret = arizona_poll_reg(arizona, 5, ARIZONA_WRITE_SEQUENCER_CTRL_1,
			       ARIZONA_WSEQ_BUSY, 0);
	if (ret != 0) {
		regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
				ARIZONA_WSEQ_ABORT);
		ret = -ETIMEDOUT;
	}

err_sysclk:
	err = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, sysclk);
	if (err != 0) {
		dev_err(arizona->dev,
			"Failed to re-apply old SYSCLK settings: %d\n",
			err);
	}

err_fll:
	err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, fll);
	if (err != 0) {
		dev_err(arizona->dev,
			"Failed to re-apply old FLL settings: %d\n",
			err);
	}

	regcache_cache_bypass(arizona->regmap, false);

	if (ret != 0)
		return ret;
	else
		return err;
}
Example #11
0
static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
			     const struct i2c_device_id *id)
{
	struct cs42l73_private *cs42l73;
	struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
	int ret;
	unsigned int devid = 0;
	unsigned int reg;
	u32 val32;

	cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
			       GFP_KERNEL);
	if (!cs42l73)
		return -ENOMEM;

	cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
	if (IS_ERR(cs42l73->regmap)) {
		ret = PTR_ERR(cs42l73->regmap);
		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
		return ret;
	}

	if (pdata) {
		cs42l73->pdata = *pdata;
	} else {
		pdata = devm_kzalloc(&i2c_client->dev,
				     sizeof(struct cs42l73_platform_data),
				GFP_KERNEL);
		if (!pdata) {
			dev_err(&i2c_client->dev, "could not allocate pdata\n");
			return -ENOMEM;
		}
		if (i2c_client->dev.of_node) {
			if (of_property_read_u32(i2c_client->dev.of_node,
				"chgfreq", &val32) >= 0)
				pdata->chgfreq = val32;
		}
		pdata->reset_gpio = of_get_named_gpio(i2c_client->dev.of_node,
						"reset-gpio", 0);
		cs42l73->pdata = *pdata;
	}

	i2c_set_clientdata(i2c_client, cs42l73);

	if (cs42l73->pdata.reset_gpio) {
		ret = devm_gpio_request_one(&i2c_client->dev,
					    cs42l73->pdata.reset_gpio,
					    GPIOF_OUT_INIT_HIGH,
					    "CS42L73 /RST");
		if (ret < 0) {
			dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
				cs42l73->pdata.reset_gpio, ret);
			return ret;
		}
		gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
		gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
	}

	regcache_cache_bypass(cs42l73->regmap, true);

	/* initialize codec */
	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
	devid = (reg & 0xFF) << 12;

	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, &reg);
	devid |= (reg & 0xFF) << 4;

	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
	devid |= (reg & 0xF0) >> 4;

	if (devid != CS42L73_DEVID) {
		ret = -ENODEV;
		dev_err(&i2c_client->dev,
			"CS42L73 Device ID (%X). Expected %X\n",
			devid, CS42L73_DEVID);
		return ret;
	}

	ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
	if (ret < 0) {
		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
		return ret;;
	}

	dev_info(&i2c_client->dev,
		 "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);

	regcache_cache_bypass(cs42l73->regmap, false);

	ret =  snd_soc_register_codec(&i2c_client->dev,
			&soc_codec_dev_cs42l73, cs42l73_dai,
			ARRAY_SIZE(cs42l73_dai));
	if (ret < 0)
		return ret;
	return 0;
}
static int max98505_probe(struct snd_soc_codec *codec)
{
	struct max98505_priv *max98505 = snd_soc_codec_get_drvdata(codec);
	struct max98505_cdata *cdata;
	int ret = 0;
	int reg = 0;

	dev_info(codec->dev, "MONO - built on %s at %s\n",
		__DATE__,
		__TIME__);
	dev_info(codec->dev, "build number %s\n", MAX98505_REVISION);

	max98505->codec = codec;
	codec->control_data = max98505->regmap;

	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
		return ret;
	}

	max98505->sysclk = 12288000;
	max98505->volume = 0x07;

	cdata = &max98505->dai[0];
	cdata->rate = (unsigned)-1;
	cdata->fmt  = (unsigned)-1;

	reg = 0;
	ret = regmap_read(max98505->regmap, MAX98505_R0FF_VERSION, &reg);
	if ((ret < 0) || ((reg != MAX98505_VERSION) && (reg != MAX98505_VERSION1) && (reg != MAX98505_VERSION2))) {
		dev_err(codec->dev,
			"device initialization error (%d 0x%02X)\n",
			ret,
			reg);
		goto err_access;
	}
	dev_info(codec->dev, "device version 0x%02X\n", reg);

#if 0
	/* FOR DEBUGGING ONLY */
	regcache_cache_bypass(max98505->regmap, true);
	dev_info(codec->dev, "regmap cache bypass ENABLED!\n");
	/**********************/
#endif

	regmap_write(max98505->regmap, MAX98505_R038_GLOBAL_ENABLE, 0x00);

	/* It's not the default but we need to set DAI_DLY */
	regmap_write(max98505->regmap, MAX98505_R020_FORMAT, M98505_DAI_DLY_MASK);

	regmap_write(max98505->regmap, MAX98505_R021_TDM_SLOT_SELECT, 0xC8);

	regmap_write(max98505->regmap, MAX98505_R027_DOUT_HIZ_CFG1, 0xFF);
	regmap_write(max98505->regmap, MAX98505_R028_DOUT_HIZ_CFG2, 0xFF);
	regmap_write(max98505->regmap, MAX98505_R029_DOUT_HIZ_CFG3, 0xFF);
	regmap_write(max98505->regmap, MAX98505_R02A_DOUT_HIZ_CFG4, 0xF0);

	regmap_write(max98505->regmap, MAX98505_R02C_FILTERS, 0xD8);

//	regmap_write(max98505->regmap, MAX98505_R034_ALC_CONFIGURATION, 0xF8);
	regmap_write(max98505->regmap, MAX98505_R034_ALC_CONFIGURATION, 0x12);


	/*****************************************************************/
	/* Set boost output to minimum until DSM is implemented          */
	regmap_write(max98505->regmap, MAX98505_R037_CONFIGURATION, 0xF0);
	/*****************************************************************/

	// Disable ALC muting
	regmap_write(max98505->regmap, MAX98505_R03A_BOOST_LIMITER, 0xF8);

	regmap_update_bits(max98505->regmap, MAX98505_R02D_GAIN,
			M98505_DAC_IN_SEL_MASK, M98505_DAC_IN_SEL_DIV2_SUMMED_DAI);

	max98505_handle_pdata(codec);
	max98505_add_widgets(codec);

	ret = sysfs_create_group(&codec->dev->kobj, &maxim_attribute_group);
	if(ret) {
		pr_err("failed to create sysfs group [%d]", ret);
	}
err_access:

	pr_info("%s: exit %d\n", __func__, ret);
	ret = 0;   // temp
	return ret;
}
Example #13
0
static void sc16is7xx_set_termios(struct uart_port *port,
				  struct ktermios *termios,
				  struct ktermios *old)
{
	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
	unsigned int lcr, flow = 0;
	int baud;

	/* Mask termios capabilities we don't support */
	termios->c_cflag &= ~CMSPAR;

	/* Word size */
	switch (termios->c_cflag & CSIZE) {
	case CS5:
		lcr = SC16IS7XX_LCR_WORD_LEN_5;
		break;
	case CS6:
		lcr = SC16IS7XX_LCR_WORD_LEN_6;
		break;
	case CS7:
		lcr = SC16IS7XX_LCR_WORD_LEN_7;
		break;
	case CS8:
		lcr = SC16IS7XX_LCR_WORD_LEN_8;
		break;
	default:
		lcr = SC16IS7XX_LCR_WORD_LEN_8;
		termios->c_cflag &= ~CSIZE;
		termios->c_cflag |= CS8;
		break;
	}

	/* Parity */
	if (termios->c_cflag & PARENB) {
		lcr |= SC16IS7XX_LCR_PARITY_BIT;
		if (!(termios->c_cflag & PARODD))
			lcr |= SC16IS7XX_LCR_EVENPARITY_BIT;
	}

	/* Stop bits */
	if (termios->c_cflag & CSTOPB)
		lcr |= SC16IS7XX_LCR_STOPLEN_BIT; /* 2 stops */

	/* Set read status mask */
	port->read_status_mask = SC16IS7XX_LSR_OE_BIT;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= SC16IS7XX_LSR_PE_BIT |
					  SC16IS7XX_LSR_FE_BIT;
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= SC16IS7XX_LSR_BI_BIT;

	/* Set status ignore mask */
	port->ignore_status_mask = 0;
	if (termios->c_iflag & IGNBRK)
		port->ignore_status_mask |= SC16IS7XX_LSR_BI_BIT;
	if (!(termios->c_cflag & CREAD))
		port->ignore_status_mask |= SC16IS7XX_LSR_BRK_ERROR_MASK;

	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
			     SC16IS7XX_LCR_CONF_MODE_B);

	/* Configure flow control */
	regcache_cache_bypass(s->regmap, true);
	sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]);
	sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]);
	if (termios->c_cflag & CRTSCTS)
		flow |= SC16IS7XX_EFR_AUTOCTS_BIT |
			SC16IS7XX_EFR_AUTORTS_BIT;
	if (termios->c_iflag & IXON)
		flow |= SC16IS7XX_EFR_SWFLOW3_BIT;
	if (termios->c_iflag & IXOFF)
		flow |= SC16IS7XX_EFR_SWFLOW1_BIT;

	sc16is7xx_port_write(port, SC16IS7XX_EFR_REG, flow);
	regcache_cache_bypass(s->regmap, false);

	/* Update LCR register */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);

	/* Get baud rate generator configuration */
	baud = uart_get_baud_rate(port, termios, old,
				  port->uartclk / 16 / 4 / 0xffff,
				  port->uartclk / 16);

	/* Setup baudrate generator */
	baud = sc16is7xx_set_baud(port, baud);

	/* Update timeout according to new baud rate */
	uart_update_timeout(port, termios->c_cflag, baud);
}
Example #14
0
static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
				unsigned int iir)
{
	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
	unsigned int lsr = 0, ch, flag, bytes_read, i;
	bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false;

	if (unlikely(rxlen >= sizeof(s->buf))) {
		dev_warn_ratelimited(port->dev,
				     "Port %i: Possible RX FIFO overrun: %d\n",
				     port->line, rxlen);
		port->icount.buf_overrun++;
		/* Ensure sanity of RX level */
		rxlen = sizeof(s->buf);
	}

	while (rxlen) {
		/* Only read lsr if there are possible errors in FIFO */
		if (read_lsr) {
			lsr = sc16is7xx_port_read(port, SC16IS7XX_LSR_REG);
			if (!(lsr & SC16IS7XX_LSR_FIFOE_BIT))
				read_lsr = false; /* No errors left in FIFO */
		} else
			lsr = 0;

		if (read_lsr) {
			s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG);
			bytes_read = 1;
		} else {
			regcache_cache_bypass(s->regmap, true);
			regmap_raw_read(s->regmap, SC16IS7XX_RHR_REG,
					s->buf, rxlen);
			regcache_cache_bypass(s->regmap, false);
			bytes_read = rxlen;
		}

		lsr &= SC16IS7XX_LSR_BRK_ERROR_MASK;

		port->icount.rx++;
		flag = TTY_NORMAL;

		if (unlikely(lsr)) {
			if (lsr & SC16IS7XX_LSR_BI_BIT) {
				port->icount.brk++;
				if (uart_handle_break(port))
					continue;
			} else if (lsr & SC16IS7XX_LSR_PE_BIT)
				port->icount.parity++;
			else if (lsr & SC16IS7XX_LSR_FE_BIT)
				port->icount.frame++;
			else if (lsr & SC16IS7XX_LSR_OE_BIT)
				port->icount.overrun++;

			lsr &= port->read_status_mask;
			if (lsr & SC16IS7XX_LSR_BI_BIT)
				flag = TTY_BREAK;
			else if (lsr & SC16IS7XX_LSR_PE_BIT)
				flag = TTY_PARITY;
			else if (lsr & SC16IS7XX_LSR_FE_BIT)
				flag = TTY_FRAME;
			else if (lsr & SC16IS7XX_LSR_OE_BIT)
				flag = TTY_OVERRUN;
		}

		for (i = 0; i < bytes_read; ++i) {
			ch = s->buf[i];
			if (uart_handle_sysrq_char(port, ch))
				continue;

			if (lsr & port->ignore_status_mask)
				continue;

			uart_insert_char(port, lsr, SC16IS7XX_LSR_OE_BIT, ch,
					 flag);
		}
		rxlen -= bytes_read;
	}

	tty_flip_buffer_push(&port->state->port);
}