Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH] dt-bindings: Remove leading 0x from bindings notation
From: David Daney @ 2017-11-29 23:21 UTC (permalink / raw)
  To: Mathieu Malaterre, Rob Herring
  Cc: linux-kernel, devicetree, Marco Franchi, linux-mips
In-Reply-To: <20171129205515.9009-1-malat@debian.org>

On 11/29/2017 12:55 PM, Mathieu Malaterre wrote:
> Improve the binding example by removing all the leading 0x to fix the
> following dtc warnings:
> 
> Warning (unit_address_format): Node /XXX unit name should not have leading "0x"

How does it fix the warnings?  You are not changing the .dts files that 
are compiled.

This may also cause the binding documentation to differ from the reality 
of what the actual device trees contain.

> 
> Converted using the following command:
> 
> find Documentation/devicetree/bindings -name "*.txt" -exec sed -i -e 's/([^ ])\@0x([0-9a-f])/$1\@$2/g' {} +
> 
> This is a follow up to commit 48c926cd3414
> 
> Signed-off-by: Mathieu Malaterre <malat@debian.org>
> ---
> I've also checked using the original perl command that I did not introduce:
> 
> Warning (unit_address_format): Node /XXX unit name should not have leading 0s
> 
>   Documentation/devicetree/bindings/arm/ccn.txt                |  2 +-
>   Documentation/devicetree/bindings/arm/omap/crossbar.txt      |  2 +-
>   .../devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt      |  2 +-
>   Documentation/devicetree/bindings/clock/axi-clkgen.txt       |  2 +-
>   .../devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt     |  2 +-
>   Documentation/devicetree/bindings/clock/exynos4-clock.txt    |  2 +-
>   Documentation/devicetree/bindings/clock/exynos5250-clock.txt |  2 +-
>   Documentation/devicetree/bindings/clock/exynos5410-clock.txt |  2 +-
>   Documentation/devicetree/bindings/clock/exynos5420-clock.txt |  2 +-
>   Documentation/devicetree/bindings/clock/exynos5440-clock.txt |  2 +-
>   .../devicetree/bindings/clock/ti-keystone-pllctrl.txt        |  2 +-
>   Documentation/devicetree/bindings/clock/zx296702-clk.txt     |  4 ++--
>   Documentation/devicetree/bindings/crypto/fsl-sec4.txt        |  4 ++--
>   .../devicetree/bindings/devfreq/event/rockchip-dfi.txt       |  2 +-
>   Documentation/devicetree/bindings/display/atmel,lcdc.txt     |  4 ++--
>   Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt    |  4 ++--
>   Documentation/devicetree/bindings/dma/zxdma.txt              |  2 +-
>   Documentation/devicetree/bindings/gpio/gpio-altera.txt       |  2 +-
>   Documentation/devicetree/bindings/i2c/i2c-jz4780.txt         |  2 +-
>   Documentation/devicetree/bindings/iio/pressure/hp03.txt      |  2 +-
>   .../devicetree/bindings/input/touchscreen/bu21013.txt        |  2 +-
>   .../devicetree/bindings/interrupt-controller/arm,gic.txt     |  4 ++--
>   .../bindings/interrupt-controller/img,meta-intc.txt          |  2 +-
>   .../bindings/interrupt-controller/img,pdc-intc.txt           |  2 +-
>   .../bindings/interrupt-controller/st,spear3xx-shirq.txt      |  2 +-
>   Documentation/devicetree/bindings/mailbox/altera-mailbox.txt |  6 +++---
>   .../devicetree/bindings/mailbox/brcm,iproc-pdc-mbox.txt      |  2 +-
>   Documentation/devicetree/bindings/media/exynos5-gsc.txt      |  2 +-
>   Documentation/devicetree/bindings/media/mediatek-vcodec.txt  |  2 +-
>   Documentation/devicetree/bindings/media/rcar_vin.txt         |  2 +-
>   Documentation/devicetree/bindings/media/samsung-fimc.txt     |  2 +-
>   Documentation/devicetree/bindings/media/sh_mobile_ceu.txt    |  2 +-
>   Documentation/devicetree/bindings/media/video-interfaces.txt | 10 +++++-----
>   .../devicetree/bindings/memory-controllers/ti/emif.txt       |  2 +-
>   .../devicetree/bindings/mfd/ti-keystone-devctrl.txt          |  2 +-
>   Documentation/devicetree/bindings/misc/brcm,kona-smc.txt     |  2 +-
>   Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.txt    |  2 +-
>   Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt   |  2 +-
>   Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt      |  4 ++--
>   Documentation/devicetree/bindings/mtd/gpmc-nor.txt           |  6 +++---
>   Documentation/devicetree/bindings/mtd/mtk-nand.txt           |  2 +-
>   Documentation/devicetree/bindings/net/altera_tse.txt         |  4 ++--
>   Documentation/devicetree/bindings/net/mdio.txt               |  2 +-
>   Documentation/devicetree/bindings/net/socfpga-dwmac.txt      |  2 +-
>   Documentation/devicetree/bindings/nios2/nios2.txt            |  2 +-
>   Documentation/devicetree/bindings/pci/altera-pcie.txt        |  2 +-
>   Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt     |  2 +-
>   Documentation/devicetree/bindings/pci/hisilicon-pcie.txt     |  2 +-
>   Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt      |  2 +-
>   .../devicetree/bindings/pinctrl/brcm,cygnus-pinmux.txt       |  2 +-
>   Documentation/devicetree/bindings/pinctrl/pinctrl-atlas7.txt |  4 ++--
>   Documentation/devicetree/bindings/pinctrl/pinctrl-sirf.txt   |  2 +-
>   .../devicetree/bindings/pinctrl/rockchip,pinctrl.txt         |  4 ++--
>   Documentation/devicetree/bindings/regulator/regulator.txt    |  2 +-
>   Documentation/devicetree/bindings/serial/efm32-uart.txt      |  2 +-
>   .../devicetree/bindings/serio/allwinner,sun4i-ps2.txt        |  2 +-
>   .../devicetree/bindings/soc/ti/keystone-navigator-qmss.txt   |  2 +-
>   Documentation/devicetree/bindings/sound/adi,axi-i2s.txt      |  2 +-
>   Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt |  2 +-
>   Documentation/devicetree/bindings/sound/ak4613.txt           |  2 +-
>   Documentation/devicetree/bindings/sound/ak4642.txt           |  2 +-
>   Documentation/devicetree/bindings/sound/max98371.txt         |  2 +-
>   Documentation/devicetree/bindings/sound/max9867.txt          |  2 +-
>   Documentation/devicetree/bindings/sound/renesas,fsi.txt      |  2 +-
>   Documentation/devicetree/bindings/sound/rockchip-spdif.txt   |  2 +-
>   Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt |  8 ++++----
>   Documentation/devicetree/bindings/spi/efm32-spi.txt          |  2 +-
>   Documentation/devicetree/bindings/thermal/thermal.txt        | 12 ++++++------
>   Documentation/devicetree/bindings/ufs/ufs-qcom.txt           |  4 ++--
>   Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt      |  2 +-
>   Documentation/devicetree/bindings/usb/ehci-st.txt            |  2 +-
>   Documentation/devicetree/bindings/usb/ohci-st.txt            |  2 +-
>   .../devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt      |  2 +-
>   73 files changed, 99 insertions(+), 99 deletions(-)
> 

^ permalink raw reply

* Re: [PATCH 3/4] RFC: net: dsa: Add bindings for Realtek SMI DSAs
From: Linus Walleij @ 2017-11-29 23:19 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Vivien Didelot, Florian Fainelli, netdev-u79uwXL29TY76Z2rM5mHXA,
	Antti Seppälä, Roman Yeryomin, Colin Leitner,
	Gabor Juhos,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
In-Reply-To: <20171129215659.GC1706-g2DYL2Zd6BY@public.gmane.org>

On Wed, Nov 29, 2017 at 10:56 PM, Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org> wrote:

> I think the problem might be, you are using the DSA provided MDIO bus.
> The Marvell switches has a similar setup in terms of interrupts. The
> PHY interrupts appear within the switch. So i implemented an interrupt
> controller, just the same as you.
>
> The problem is, the DSA provided MDIO bus is not linked to device
> tree. So you cannot have phy nodes in device tree associated to it.
>
> What i did for the Marvell driver is that driver itself implements an
> MDIO bus (two actually in some chips), and the internal or external
> PHYs are placed on the switch drivers MDIO bus, rather than the DSA
> MDIO bus. The switch driver MDIO bus links to an mdio node in device
> tree. I can then have interrupt properties in the phys on this MDIO
> bus in device tree.
>
> What actually might make sense, is to have the DSA MDIO bus look
> inside the switches device tree node and see if there is an mdio
> node. If so allow dsa_switch_setup() to use of_mdiobus_register()
> instead of mdiobus_register().

Aha I think I see where my thinking went wrong.

I have been assuming (thought it was intuitive...) that ports and
PHYs are mapped 1:1.

So I assumed the port with reg = <N> is also the PHY with
reg = <N>

So naturally I added the PHY interrupt to the port node.

So you are saying that the PHY and the port are two
very disparate things in DSA terminology?

I guess all ports except the CPU port actually have
a 1:1 mapped PHY though, am I right?

Or are there in pracice things such that reg is different
on the port and the PHY connected to it? Then it makes
much sense to put an MDIO bus inside the switch DT
node and populate the PHY interrupts from there as you
say.

I can take a stab at fixing that if that is what we want.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v4 7/8] netdev: octeon-ethernet: Add Cavium Octeon III support.
From: David Daney @ 2017-11-29 23:04 UTC (permalink / raw)
  To: Andrew Lunn, David Daney
  Cc: Mark Rutland, linux-mips, devel, devicetree, netdev, linux-kernel,
	ralf, Carlos Munoz, Rob Herring, Steven J. Hill,
	Greg Kroah-Hartman, Florian Fainelli, James Hogan,
	David S. Miller
In-Reply-To: <20171129225609.GE1706@lunn.ch>

On 11/29/2017 02:56 PM, Andrew Lunn wrote:
> On Tue, Nov 28, 2017 at 04:55:39PM -0800, David Daney wrote:
>> +static int bgx_probe(struct platform_device *pdev)
>> +{
>> +	struct mac_platform_data platform_data;
>> +	const __be32 *reg;
>> +	u32 port;
>> +	u64 addr;
>> +	struct device_node *child;
>> +	struct platform_device *new_dev;
>> +	struct platform_device *pki_dev;
>> +	int numa_node, interface;
>> +	int i;
>> +	int r = 0;
>> +	char id[64];
>> +	u64 data;
>> +
>> +	reg = of_get_property(pdev->dev.of_node, "reg", NULL);
>> +	addr = of_translate_address(pdev->dev.of_node, reg);
>> +	interface = (addr >> 24) & 0xf;
>> +	numa_node = (addr >> 36) & 0x7;
> 
> Hi David
> 
> You have these two a few times in the code. Maybe add a helper to do
> it? The NUMA one i assume could go somewhere in the SoC code?
> 

Thanks for looking at it, I will try with helpers.


The rest of your comments below raise valid points, I will fix those too.




>> +static int bgx_mix_init_from_fdt(void)
>> +{
>> +	struct device_node	*node;
>> +	struct device_node	*parent = NULL;
>> +	int			mix = 0;
> 
>> +		/* Get the lmac index */
>> +		reg = of_get_property(lmac_fdt_node, "reg", NULL);
>> +		if (!reg)
>> +			goto err;
>> +
>> +		mix_port_lmacs[mix].lmac = *reg;
> 
> I don't think of_get_property() deals with endianness. Is there any
> danger of this driver being used on hardware with the other endianness
> to what you have tested?
> 
>> +/**
>> + * bgx_pki_init_from_param - Initialize the list of lmacs that connect to the
>> + *			     pki from information in the "pki_port" parameter.
>> + *
>> + *			     The pki_port parameter format is as follows:
>> + *			     pki_port=nbl
>> + *			     where:
>> + *				n = node
>> + *				b = bgx
>> + *				l = lmac
>> + *
>> + *			     Commas must be used to separate multiple lmacs:
>> + *			     pki_port=000,100,110
>> + *
>> + *			     Asterisks (*) specify all possible characters in
>> + *			     the subset:
>> + *			     pki_port=00* (all lmacs of node0 bgx0).
>> + *
>> + *			     Missing lmacs identifiers default to all
>> + *			     possible characters in the subset:
>> + *			     pki_port=00 (all lmacs on node0 bgx0)
>> + *
>> + *			     Brackets ('[' and ']') specify the valid
>> + *			     characters in the subset:
>> + *			     pki_port=00[01] (lmac0 and lmac1 of node0 bgx0).
>> + *
>> + * Returns 0 if successful.
>> + * Returns <0 for error codes.
> 
> I've not used kerneldoc much, but i suspect this is wrongly formated:
> 
> https://www.kernel.org/doc/html/v4.9/kernel-documentation.html#function-documentation
> 
>> +int bgx_port_ethtool_set_settings(struct net_device	*netdev,
>> +				  struct ethtool_cmd	*cmd)
>> +{
>> +	struct bgx_port_priv *p = bgx_port_netdev2priv(netdev);
>> +
>> +	if (!capable(CAP_NET_ADMIN))
>> +		return -EPERM;
> 
> Not required. The enforces this. See dev_ethtool()
> 
>> +
>> +	if (p->phydev)
>> +		return phy_ethtool_sset(p->phydev, cmd);
>> +
>> +	return -EOPNOTSUPP;
>> +}
>> +EXPORT_SYMBOL(bgx_port_ethtool_set_settings);
>> +
>> +int bgx_port_ethtool_nway_reset(struct net_device *netdev)
>> +{
>> +	struct bgx_port_priv *p = bgx_port_netdev2priv(netdev);
>> +
>> +	if (!capable(CAP_NET_ADMIN))
>> +		return -EPERM;
> 
> Also not needed.
> 
>> +static void bgx_port_adjust_link(struct net_device *netdev)
>> +{
>> +	struct bgx_port_priv	*priv = bgx_port_netdev2priv(netdev);
>> +	bool			link_changed = false;
>> +	unsigned int		link;
>> +	unsigned int		speed;
>> +	unsigned int		duplex;
>> +
>> +	mutex_lock(&priv->lock);
>> +
>> +	if (!priv->phydev->link && priv->last_status.link)
>> +		link_changed = true;
>> +
>> +	if (priv->phydev->link &&
>> +	    (priv->last_status.link != priv->phydev->link ||
>> +	     priv->last_status.duplex != priv->phydev->duplex ||
>> +	     priv->last_status.speed != priv->phydev->speed))
>> +		link_changed = true;
>> +
>> +	link = priv->phydev->link;
>> +	priv->last_status.link = priv->phydev->link;
>> +
>> +	speed = priv->phydev->speed;
>> +	priv->last_status.speed = priv->phydev->speed;
>> +
>> +	duplex = priv->phydev->duplex;
>> +	priv->last_status.duplex = priv->phydev->duplex;
>> +
>> +	mutex_unlock(&priv->lock);
>> +
>> +	if (link_changed) {
>> +		struct port_status status;
>> +
>> +		phy_print_status(priv->phydev);
>> +
>> +		status.link = link ? 1 : 0;
>> +		status.duplex = duplex;
>> +		status.speed = speed;
>> +		if (!link) {
>> +			netif_carrier_off(netdev);
>> +			 /* Let TX drain. FIXME check that it is drained. */
>> +			mdelay(50);
>> +		}
>> +		priv->set_link(priv, status);
>> +		if (link)
>> +			netif_carrier_on(netdev);
> 
> The code should do netif_carrier_on/off for you. See phy_link_change()
> 
>> +static void bgx_port_check_state(struct work_struct *work)
>> +{
>> +	struct bgx_port_priv	*priv;
>> +	struct port_status	status;
>> +
>> +	priv = container_of(work, struct bgx_port_priv, dwork.work);
>> +
>> +	status = priv->get_link(priv);
>> +
>> +	if (!status.link &&
>> +	    priv->mode != PORT_MODE_SGMII && priv->mode != PORT_MODE_RGMII)
>> +		bgx_port_init_xaui_link(priv);
>> +
>> +	if (priv->last_status.link != status.link) {
>> +		priv->last_status.link = status.link;
>> +		if (status.link)
>> +			netdev_info(priv->netdev, "Link is up - %d/%s\n",
>> +				    status.speed,
>> +				    status.duplex == DUPLEX_FULL ? "Full" : "Half");
> 
> You already have phy_print_status() in bgx_port_adjust_link(). Do you need this here?
> 
>> +		else
>> +			netdev_info(priv->netdev, "Link is down\n");
>> +	}
>> +
>> +	mutex_lock(&priv->lock);
>> +	if (priv->work_queued)
>> +		queue_delayed_work(check_state_wq, &priv->dwork, HZ);
>> +	mutex_unlock(&priv->lock);
>> +}
>> +
>> +int bgx_port_enable(struct net_device *netdev)
>> +{
> 
> 
>> +	} else {
>> +		priv->phydev = of_phy_connect(netdev, priv->phy_np,
>> +					      bgx_port_adjust_link, 0, priv->phy_mode);
>> +		if (!priv->phydev)
>> +			return -ENODEV;
>> +
>> +		netif_carrier_off(netdev);
>> +
>> +		if (priv->phydev)
> 
> You already checked this above.
> 
>> +			phy_start_aneg(priv->phydev);
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(bgx_port_enable);
>> +
>> +int bgx_port_change_mtu(struct net_device *netdev, int new_mtu)
>> +{
>> +	struct bgx_port_priv *priv = bgx_port_netdev2priv(netdev);
>> +	int max_frame;
>> +
>> +	if (new_mtu < 60 || new_mtu > 65392) {
> 
> See dev_set_mtu(). If you have done your initialisation correctly, this
> won't happen.
> 
>> +static int bgx_port_probe(struct platform_device *pdev)
>> +{
>> +	switch (priv->mode) {
>> +	case PORT_MODE_SGMII:
>> +		if (priv->phy_np &&
>> +		    priv->phy_mode != PHY_INTERFACE_MODE_SGMII)
>> +			dev_warn(&pdev->dev, "SGMII phy mode mismatch.\n");
>> +		goto set_link_functions;
>> +	case PORT_MODE_RGMII:
>> +		if (priv->phy_np &&
>> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII &&
>> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII_ID &&
>> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII_RXID &&
>> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII_TXID)
> 
> phy_interface_mode_is_rgmii()
> 
> More later, maybe.
> 
>       Andrew
> 

^ permalink raw reply

* Re: [PATCH v4 7/8] netdev: octeon-ethernet: Add Cavium Octeon III support.
From: Andrew Lunn @ 2017-11-29 22:56 UTC (permalink / raw)
  To: David Daney
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
	James Hogan, netdev-u79uwXL29TY76Z2rM5mHXA, David S. Miller,
	Rob Herring, Mark Rutland, devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Steven J. Hill, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Florian Fainelli, Carlos Munoz
In-Reply-To: <20171129005540.28829-8-david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>

On Tue, Nov 28, 2017 at 04:55:39PM -0800, David Daney wrote:
> +static int bgx_probe(struct platform_device *pdev)
> +{
> +	struct mac_platform_data platform_data;
> +	const __be32 *reg;
> +	u32 port;
> +	u64 addr;
> +	struct device_node *child;
> +	struct platform_device *new_dev;
> +	struct platform_device *pki_dev;
> +	int numa_node, interface;
> +	int i;
> +	int r = 0;
> +	char id[64];
> +	u64 data;
> +
> +	reg = of_get_property(pdev->dev.of_node, "reg", NULL);
> +	addr = of_translate_address(pdev->dev.of_node, reg);
> +	interface = (addr >> 24) & 0xf;
> +	numa_node = (addr >> 36) & 0x7;

Hi David

You have these two a few times in the code. Maybe add a helper to do
it? The NUMA one i assume could go somewhere in the SoC code?

> +static int bgx_mix_init_from_fdt(void)
> +{
> +	struct device_node	*node;
> +	struct device_node	*parent = NULL;
> +	int			mix = 0;

> +		/* Get the lmac index */
> +		reg = of_get_property(lmac_fdt_node, "reg", NULL);
> +		if (!reg)
> +			goto err;
> +
> +		mix_port_lmacs[mix].lmac = *reg;

I don't think of_get_property() deals with endianness. Is there any
danger of this driver being used on hardware with the other endianness
to what you have tested?

> +/**
> + * bgx_pki_init_from_param - Initialize the list of lmacs that connect to the
> + *			     pki from information in the "pki_port" parameter.
> + *
> + *			     The pki_port parameter format is as follows:
> + *			     pki_port=nbl
> + *			     where:
> + *				n = node
> + *				b = bgx
> + *				l = lmac
> + *
> + *			     Commas must be used to separate multiple lmacs:
> + *			     pki_port=000,100,110
> + *
> + *			     Asterisks (*) specify all possible characters in
> + *			     the subset:
> + *			     pki_port=00* (all lmacs of node0 bgx0).
> + *
> + *			     Missing lmacs identifiers default to all
> + *			     possible characters in the subset:
> + *			     pki_port=00 (all lmacs on node0 bgx0)
> + *
> + *			     Brackets ('[' and ']') specify the valid
> + *			     characters in the subset:
> + *			     pki_port=00[01] (lmac0 and lmac1 of node0 bgx0).
> + *
> + * Returns 0 if successful.
> + * Returns <0 for error codes.

I've not used kerneldoc much, but i suspect this is wrongly formated:

https://www.kernel.org/doc/html/v4.9/kernel-documentation.html#function-documentation

> +int bgx_port_ethtool_set_settings(struct net_device	*netdev,
> +				  struct ethtool_cmd	*cmd)
> +{
> +	struct bgx_port_priv *p = bgx_port_netdev2priv(netdev);
> +
> +	if (!capable(CAP_NET_ADMIN))
> +		return -EPERM;

Not required. The enforces this. See dev_ethtool()

> +
> +	if (p->phydev)
> +		return phy_ethtool_sset(p->phydev, cmd);
> +
> +	return -EOPNOTSUPP;
> +}
> +EXPORT_SYMBOL(bgx_port_ethtool_set_settings);
> +
> +int bgx_port_ethtool_nway_reset(struct net_device *netdev)
> +{
> +	struct bgx_port_priv *p = bgx_port_netdev2priv(netdev);
> +
> +	if (!capable(CAP_NET_ADMIN))
> +		return -EPERM;

Also not needed.

> +static void bgx_port_adjust_link(struct net_device *netdev)
> +{
> +	struct bgx_port_priv	*priv = bgx_port_netdev2priv(netdev);
> +	bool			link_changed = false;
> +	unsigned int		link;
> +	unsigned int		speed;
> +	unsigned int		duplex;
> +
> +	mutex_lock(&priv->lock);
> +
> +	if (!priv->phydev->link && priv->last_status.link)
> +		link_changed = true;
> +
> +	if (priv->phydev->link &&
> +	    (priv->last_status.link != priv->phydev->link ||
> +	     priv->last_status.duplex != priv->phydev->duplex ||
> +	     priv->last_status.speed != priv->phydev->speed))
> +		link_changed = true;
> +
> +	link = priv->phydev->link;
> +	priv->last_status.link = priv->phydev->link;
> +
> +	speed = priv->phydev->speed;
> +	priv->last_status.speed = priv->phydev->speed;
> +
> +	duplex = priv->phydev->duplex;
> +	priv->last_status.duplex = priv->phydev->duplex;
> +
> +	mutex_unlock(&priv->lock);
> +
> +	if (link_changed) {
> +		struct port_status status;
> +
> +		phy_print_status(priv->phydev);
> +
> +		status.link = link ? 1 : 0;
> +		status.duplex = duplex;
> +		status.speed = speed;
> +		if (!link) {
> +			netif_carrier_off(netdev);
> +			 /* Let TX drain. FIXME check that it is drained. */
> +			mdelay(50);
> +		}
> +		priv->set_link(priv, status);
> +		if (link)
> +			netif_carrier_on(netdev);

The code should do netif_carrier_on/off for you. See phy_link_change()

> +static void bgx_port_check_state(struct work_struct *work)
> +{
> +	struct bgx_port_priv	*priv;
> +	struct port_status	status;
> +
> +	priv = container_of(work, struct bgx_port_priv, dwork.work);
> +
> +	status = priv->get_link(priv);
> +
> +	if (!status.link &&
> +	    priv->mode != PORT_MODE_SGMII && priv->mode != PORT_MODE_RGMII)
> +		bgx_port_init_xaui_link(priv);
> +
> +	if (priv->last_status.link != status.link) {
> +		priv->last_status.link = status.link;
> +		if (status.link)
> +			netdev_info(priv->netdev, "Link is up - %d/%s\n",
> +				    status.speed,
> +				    status.duplex == DUPLEX_FULL ? "Full" : "Half");

You already have phy_print_status() in bgx_port_adjust_link(). Do you need this here?

> +		else
> +			netdev_info(priv->netdev, "Link is down\n");
> +	}
> +
> +	mutex_lock(&priv->lock);
> +	if (priv->work_queued)
> +		queue_delayed_work(check_state_wq, &priv->dwork, HZ);
> +	mutex_unlock(&priv->lock);
> +}
> +
> +int bgx_port_enable(struct net_device *netdev)
> +{


> +	} else {
> +		priv->phydev = of_phy_connect(netdev, priv->phy_np,
> +					      bgx_port_adjust_link, 0, priv->phy_mode);
> +		if (!priv->phydev)
> +			return -ENODEV;
> +
> +		netif_carrier_off(netdev);
> +
> +		if (priv->phydev)

You already checked this above.

> +			phy_start_aneg(priv->phydev);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(bgx_port_enable);
> +
> +int bgx_port_change_mtu(struct net_device *netdev, int new_mtu)
> +{
> +	struct bgx_port_priv *priv = bgx_port_netdev2priv(netdev);
> +	int max_frame;
> +
> +	if (new_mtu < 60 || new_mtu > 65392) {

See dev_set_mtu(). If you have done your initialisation correctly, this
won't happen.

> +static int bgx_port_probe(struct platform_device *pdev)
> +{
> +	switch (priv->mode) {
> +	case PORT_MODE_SGMII:
> +		if (priv->phy_np &&
> +		    priv->phy_mode != PHY_INTERFACE_MODE_SGMII)
> +			dev_warn(&pdev->dev, "SGMII phy mode mismatch.\n");
> +		goto set_link_functions;
> +	case PORT_MODE_RGMII:
> +		if (priv->phy_np &&
> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII &&
> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII_ID &&
> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII_RXID &&
> +		    priv->phy_mode != PHY_INTERFACE_MODE_RGMII_TXID)

phy_interface_mode_is_rgmii()

More later, maybe.

     Andrew
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [patch v12 2/4] drivers: jtag: Add Aspeed SoC 24xx and 25xx families JTAG master driver
From: Kun Yi @ 2017-11-29 22:51 UTC (permalink / raw)
  To: Oleksandr Shamray
  Cc: gregkh, arnd, system-sw-low-level, devicetree, jiri, vadimp,
	linux-api, OpenBMC Maillist, linux-kernel, openocd-devel-owner,
	mec, Jiri Pirko, robh+dt, linux-serial, tklauser, mchehab, davem,
	linux-arm-kernel
In-Reply-To: <1510675867-24276-3-git-send-email-oleksandrs@mellanox.com>

Thanks for working on the driver, Oleksandr. I gave this a try on a
board with Aspeed 2520. One question below:

On Tue, Nov 14, 2017 at 8:11 AM, Oleksandr Shamray
<oleksandrs@mellanox.com> wrote:
> Driver adds support of Aspeed 2500/2400 series SOC JTAG master controller.
>
> Driver implements the following jtag ops:
> - freq_get;
> - freq_set;
> - status_get;
> - idle;
> - xfer;
>
> It has been tested on Mellanox system with BMC equipped with
> Aspeed 2520 SoC for programming CPLD devices.
>
> Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> ---
> v11->v12
> Comments pointed by Chip Bilbrey <chip@bilbrey.org>
> - Remove access mode from xfer and idle transactions
> - Add new ioctl JTAG_SIOCMODE for set hw mode
>
> v10->v11
> v9->v10
> V8->v9
> Comments pointed by Arnd Bergmann <arnd@arndb.de>
> - add *data parameter to xfer function prototype
>
> v7->v8
> Comments pointed by Joel Stanley <joel.stan@gmail.com>
> - aspeed_jtag_init replace goto to return;
> - change input variables type from __u32 to u32
>   in functios freq_get, freq_set, status_get
> - change sm_ variables type from char to u8
> - in jatg_init add disable clocks on error case
> - remove release_mem_region on error case
> - remove devm_free_irq on jtag_deinit
> - Fix misspelling Disabe/Disable
> - Change compatible string to ast2400 and ast2000
>
> v6->v7
> Notifications from kbuild test robot <lkp@intel.com>
> - Add include <linux/types.h> to jtag-asapeed.c
>
> v5->v6
> v4->v5
> Comments pointed by Arnd Bergmann <arnd@arndb.de>
> - Added HAS_IOMEM dependence in Kconfig to avoid
>   "undefined reference to `devm_ioremap_resource'" error,
>   because in some arch this not supported
>
> v3->v4
> Comments pointed by Arnd Bergmann <arnd@arndb.de>
> - change transaction pointer tdio type  to __u64
> - change internal status type from enum to __u32
>
> v2->v3
>
> v1->v2
> Comments pointed by Greg KH <gregkh@linuxfoundation.org>
> - change license type from GPLv2/BSD to GPLv2
>
> Comments pointed by Neil Armstrong <narmstrong@baylibre.com>
> - Add clk_prepare_enable/clk_disable_unprepare in clock init/deinit
> - Change .compatible to soc-specific compatible names
>   aspeed,aspeed4000-jtag/aspeed5000-jtag
> - Added dt-bindings
>
> Comments pointed by Arnd Bergmann <arnd@arndb.de>
> - Reorder functions and removed the forward declarations
> - Add static const qualifier to state machine states transitions
> - Change .compatible to soc-specific compatible names
>   aspeed,aspeed4000-jtag/aspeed5000-jtag
> - Add dt-bindings
>
> Comments pointed by Randy Dunlap <rdunlap@infradead.org>
> - Change module name jtag-aspeed in description in Kconfig
>
> Comments pointed by kbuild test robot <lkp@intel.com>
> - Remove invalid include <asm/mach-types.h>
> - add resource_size instead of calculation
> ---
>  drivers/jtag/Kconfig       |   13 +
>  drivers/jtag/Makefile      |    1 +
>  drivers/jtag/jtag-aspeed.c |  782 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 796 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/jtag/jtag-aspeed.c
>
> diff --git a/drivers/jtag/Kconfig b/drivers/jtag/Kconfig
> index 0fad1a3..098beb0 100644
> --- a/drivers/jtag/Kconfig
> +++ b/drivers/jtag/Kconfig
> @@ -14,3 +14,16 @@ menuconfig JTAG
>
>           To compile this driver as a module, choose M here: the module will
>           be called jtag.
> +
> +menuconfig JTAG_ASPEED
> +       tristate "Aspeed SoC JTAG controller support"
> +       depends on JTAG && HAS_IOMEM
> +       ---help---
> +         This provides a support for Aspeed JTAG device, equipped on
> +         Aspeed SoC 24xx and 25xx families. Drivers allows programming
> +         of hardware devices, connected to SoC through the JTAG interface.
> +
> +         If you want this support, you should say Y here.
> +
> +         To compile this driver as a module, choose M here: the module will
> +         be called jtag-aspeed.
> diff --git a/drivers/jtag/Makefile b/drivers/jtag/Makefile
> index af37493..04a855e 100644
> --- a/drivers/jtag/Makefile
> +++ b/drivers/jtag/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_JTAG)             += jtag.o
> +obj-$(CONFIG_JTAG_ASPEED)      += jtag-aspeed.o
> diff --git a/drivers/jtag/jtag-aspeed.c b/drivers/jtag/jtag-aspeed.c
> new file mode 100644
> index 0000000..a6e2417
> --- /dev/null
> +++ b/drivers/jtag/jtag-aspeed.c
> @@ -0,0 +1,782 @@
> +/*
> + * drivers/jtag/aspeed-jtag.c
> + *
> + * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
> + * Copyright (c) 2017 Oleksandr Shamray <oleksandrs@mellanox.com>
> + *
> + * Released under the GPLv2 only.
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/jtag.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <uapi/linux/jtag.h>
> +
> +#define ASPEED_JTAG_DATA               0x00
> +#define ASPEED_JTAG_INST               0x04
> +#define ASPEED_JTAG_CTRL               0x08
> +#define ASPEED_JTAG_ISR                        0x0C
> +#define ASPEED_JTAG_SW                 0x10
> +#define ASPEED_JTAG_TCK                        0x14
> +#define ASPEED_JTAG_EC                 0x18
> +
> +#define ASPEED_JTAG_DATA_MSB           0x01
> +#define ASPEED_JTAG_DATA_CHUNK_SIZE    0x20
> +
> +/* ASPEED_JTAG_CTRL: Engine Control */
> +#define ASPEED_JTAG_CTL_ENG_EN         BIT(31)
> +#define ASPEED_JTAG_CTL_ENG_OUT_EN     BIT(30)
> +#define ASPEED_JTAG_CTL_FORCE_TMS      BIT(29)
> +#define ASPEED_JTAG_CTL_INST_LEN(x)    ((x) << 20)
> +#define ASPEED_JTAG_CTL_LASPEED_INST   BIT(17)
> +#define ASPEED_JTAG_CTL_INST_EN                BIT(16)
> +#define ASPEED_JTAG_CTL_DR_UPDATE      BIT(10)
> +#define ASPEED_JTAG_CTL_DATA_LEN(x)    ((x) << 4)
> +#define ASPEED_JTAG_CTL_LASPEED_DATA   BIT(1)
> +#define ASPEED_JTAG_CTL_DATA_EN                BIT(0)
> +
> +/* ASPEED_JTAG_ISR : Interrupt status and enable */
> +#define ASPEED_JTAG_ISR_INST_PAUSE     BIT(19)
> +#define ASPEED_JTAG_ISR_INST_COMPLETE  BIT(18)
> +#define ASPEED_JTAG_ISR_DATA_PAUSE     BIT(17)
> +#define ASPEED_JTAG_ISR_DATA_COMPLETE  BIT(16)
> +#define ASPEED_JTAG_ISR_INST_PAUSE_EN  BIT(3)
> +#define ASPEED_JTAG_ISR_INST_COMPLETE_EN BIT(2)
> +#define ASPEED_JTAG_ISR_DATA_PAUSE_EN  BIT(1)
> +#define ASPEED_JTAG_ISR_DATA_COMPLETE_EN BIT(0)
> +#define ASPEED_JTAG_ISR_INT_EN_MASK    GENMASK(3, 0)
> +#define ASPEED_JTAG_ISR_INT_MASK       GENMASK(19, 16)
> +
> +/* ASPEED_JTAG_SW : Software Mode and Status */
> +#define ASPEED_JTAG_SW_MODE_EN         BIT(19)
> +#define ASPEED_JTAG_SW_MODE_TCK                BIT(18)
> +#define ASPEED_JTAG_SW_MODE_TMS                BIT(17)
> +#define ASPEED_JTAG_SW_MODE_TDIO       BIT(16)
> +
> +/* ASPEED_JTAG_TCK : TCK Control */
> +#define ASPEED_JTAG_TCK_DIVISOR_MASK   GENMASK(10, 0)
> +#define ASPEED_JTAG_TCK_GET_DIV(x)     ((x) & ASPEED_JTAG_TCK_DIVISOR_MASK)
> +
> +/* ASPEED_JTAG_EC : Controller set for go to IDLE */
> +#define ASPEED_JTAG_EC_GO_IDLE         BIT(0)
> +
> +#define ASPEED_JTAG_IOUT_LEN(len)      (ASPEED_JTAG_CTL_ENG_EN |\
> +                                        ASPEED_JTAG_CTL_ENG_OUT_EN |\
> +                                        ASPEED_JTAG_CTL_INST_LEN(len))
> +
> +#define ASPEED_JTAG_DOUT_LEN(len)      (ASPEED_JTAG_CTL_ENG_EN |\
> +                                        ASPEED_JTAG_CTL_ENG_OUT_EN |\
> +                                        ASPEED_JTAG_CTL_DATA_LEN(len))
> +
> +#define ASPEED_JTAG_TCK_WAIT           10
> +#define ASPEED_JTAG_RESET_CNTR         10
> +
> +#define ASPEED_JTAG_NAME               "jtag-aspeed"
> +
> +struct aspeed_jtag {
> +       void __iomem                    *reg_base;
> +       struct device                   *dev;
> +       struct clk                      *pclk;
> +       enum jtag_endstate              status;
> +       int                             irq;
> +       u32                             flag;
> +       wait_queue_head_t               jtag_wq;
> +       u32                             mode;
> +};
> +
> +static char *end_status_str[] = {"idle", "ir pause", "drpause"};
> +
> +static u32 aspeed_jtag_read(struct aspeed_jtag *aspeed_jtag, u32 reg)
> +{
> +       return readl(aspeed_jtag->reg_base + reg);
> +}
> +
> +static void
> +aspeed_jtag_write(struct aspeed_jtag *aspeed_jtag, u32 val, u32 reg)
> +{
> +       writel(val, aspeed_jtag->reg_base + reg);
> +}
> +
> +static int aspeed_jtag_freq_set(struct jtag *jtag, u32 freq)
> +{
> +       struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
> +       unsigned long apb_frq;
> +       u32 tck_val;
> +       u16 div;
> +
> +       apb_frq = clk_get_rate(aspeed_jtag->pclk);
> +       div = (apb_frq % freq == 0) ? (apb_frq / freq) - 1 : (apb_frq / freq);
> +       tck_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK);
> +       aspeed_jtag_write(aspeed_jtag,
> +                         (tck_val & ASPEED_JTAG_TCK_DIVISOR_MASK) | div,
> +                         ASPEED_JTAG_TCK);
> +       return 0;
> +}
> +
> +static int aspeed_jtag_freq_get(struct jtag *jtag, u32 *frq)
> +{
> +       struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
> +       u32 pclk;
> +       u32 tck;
> +
> +       pclk = clk_get_rate(aspeed_jtag->pclk);
> +       tck = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK);
> +       *frq = pclk / (ASPEED_JTAG_TCK_GET_DIV(tck) + 1);
> +
> +       return 0;
> +}
> +
> +static int aspeed_jtag_mode_set(struct jtag *jtag, u32 mode)
> +{
> +       struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
> +
> +       aspeed_jtag->mode = mode;
> +       return 0;
> +}
> +
> +static void aspeed_jtag_sw_delay(struct aspeed_jtag *aspeed_jtag, int cnt)
> +{
> +       int i;
> +
> +       for (i = 0; i < cnt; i++)
> +               aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW);
> +}
> +
> +static char aspeed_jtag_tck_cycle(struct aspeed_jtag *aspeed_jtag,
> +                                 u8 tms, u8 tdi)
> +{
> +       char tdo = 0;
> +
> +       /* TCK = 0 */
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
> +                         (tms * ASPEED_JTAG_SW_MODE_TMS) |
> +                         (tdi * ASPEED_JTAG_SW_MODE_TDIO), ASPEED_JTAG_SW);
> +
> +       aspeed_jtag_sw_delay(aspeed_jtag, ASPEED_JTAG_TCK_WAIT);
> +
> +       /* TCK = 1 */
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
> +                         ASPEED_JTAG_SW_MODE_TCK |
> +                         (tms * ASPEED_JTAG_SW_MODE_TMS) |
> +                         (tdi * ASPEED_JTAG_SW_MODE_TDIO), ASPEED_JTAG_SW);
> +
> +       if (aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW) &
> +           ASPEED_JTAG_SW_MODE_TDIO)
> +               tdo = 1;
> +
> +       aspeed_jtag_sw_delay(aspeed_jtag, ASPEED_JTAG_TCK_WAIT);
> +
> +       /* TCK = 0 */
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
> +                         (tms * ASPEED_JTAG_SW_MODE_TMS) |
> +                         (tdi * ASPEED_JTAG_SW_MODE_TDIO), ASPEED_JTAG_SW);
> +       return tdo;
> +}
> +
> +static void aspeed_jtag_wait_instruction_pause(struct aspeed_jtag *aspeed_jtag)
> +{
> +       wait_event_interruptible(aspeed_jtag->jtag_wq, aspeed_jtag->flag &
> +                                ASPEED_JTAG_ISR_INST_PAUSE);
> +       aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_INST_PAUSE;
> +}
> +
> +static void
> +aspeed_jtag_wait_instruction_complete(struct aspeed_jtag *aspeed_jtag)
> +{
> +       wait_event_interruptible(aspeed_jtag->jtag_wq, aspeed_jtag->flag &
> +                                ASPEED_JTAG_ISR_INST_COMPLETE);
> +       aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_INST_COMPLETE;
> +}
> +
> +static void
> +aspeed_jtag_wait_data_pause_complete(struct aspeed_jtag *aspeed_jtag)
> +{
> +       wait_event_interruptible(aspeed_jtag->jtag_wq, aspeed_jtag->flag &
> +                                ASPEED_JTAG_ISR_DATA_PAUSE);
> +       aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_DATA_PAUSE;
> +}
> +
> +static void aspeed_jtag_wait_data_complete(struct aspeed_jtag *aspeed_jtag)
> +{
> +       wait_event_interruptible(aspeed_jtag->jtag_wq, aspeed_jtag->flag &
> +                                ASPEED_JTAG_ISR_DATA_COMPLETE);
> +       aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_DATA_COMPLETE;
> +}
> +
> +static void aspeed_jtag_sm_cycle(struct aspeed_jtag *aspeed_jtag, const u8 *tms,
> +                                int len)
> +{
> +       int i;
> +
> +       for (i = 0; i < len; i++)
> +               aspeed_jtag_tck_cycle(aspeed_jtag, tms[i], 0);
> +}
> +
> +static void aspeed_jtag_run_test_idle_sw(struct aspeed_jtag *aspeed_jtag,
> +                                        struct jtag_run_test_idle *runtest)
> +{
> +       static const u8 sm_pause_irpause[] = {1, 1, 1, 1, 0, 1, 0};
> +       static const u8 sm_pause_drpause[] = {1, 1, 1, 0, 1, 0};
> +       static const u8 sm_idle_irpause[] = {1, 1, 0, 1, 0};
> +       static const u8 sm_idle_drpause[] = {1, 0, 1, 0};
> +       static const u8 sm_pause_idle[] = {1, 1, 0};
> +       int i;
> +
> +       /* SW mode from idle/pause-> to pause/idle */
> +       if (runtest->reset) {
> +               for (i = 0; i < ASPEED_JTAG_RESET_CNTR; i++)
> +                       aspeed_jtag_tck_cycle(aspeed_jtag, 1, 0);
> +       }
> +
> +       switch (aspeed_jtag->status) {
> +       case JTAG_STATE_IDLE:
> +               switch (runtest->endstate) {
> +               case JTAG_STATE_PAUSEIR:
> +                       /* ->DRSCan->IRSCan->IRCap->IRExit1->PauseIR */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_idle_irpause,
> +                                            sizeof(sm_idle_irpause));
> +
> +                       aspeed_jtag->status = JTAG_STATE_PAUSEIR;
> +                       break;
> +               case JTAG_STATE_PAUSEDR:
> +                       /* ->DRSCan->DRCap->DRExit1->PauseDR */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_idle_drpause,
> +                                            sizeof(sm_idle_drpause));
> +
> +                       aspeed_jtag->status = JTAG_STATE_PAUSEDR;
> +                       break;
> +               case JTAG_STATE_IDLE:
> +                       /* IDLE */
> +                       aspeed_jtag_tck_cycle(aspeed_jtag, 0, 0);
> +                       aspeed_jtag->status = JTAG_STATE_IDLE;
> +                       break;
> +               default:
> +                       break;
> +               }
> +               break;
> +
> +       case JTAG_STATE_PAUSEIR:
> +       /* Fall-through */
> +       case JTAG_STATE_PAUSEDR:
> +               /* From IR/DR Pause */
> +               switch (runtest->endstate) {
> +               case JTAG_STATE_PAUSEIR:
> +                       /*
> +                        * to Exit2 IR/DR->Updt IR/DR->DRSCan->IRSCan->IRCap->
> +                        * IRExit1->PauseIR
> +                        */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_pause_irpause,
> +                                            sizeof(sm_pause_irpause));
> +
> +                       aspeed_jtag->status = JTAG_STATE_PAUSEIR;
> +                       break;
> +               case JTAG_STATE_PAUSEDR:
> +                       /*
> +                        * to Exit2 IR/DR->Updt IR/DR->DRSCan->DRCap->
> +                        * DRExit1->PauseDR
> +                        */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_pause_drpause,
> +                                            sizeof(sm_pause_drpause));
> +                       aspeed_jtag->status = JTAG_STATE_PAUSEDR;
> +                       break;
> +               case JTAG_STATE_IDLE:
> +                       /* to Exit2 IR/DR->Updt IR/DR->IDLE */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_pause_idle,
> +                                            sizeof(sm_pause_idle));
> +                       aspeed_jtag->status = JTAG_STATE_IDLE;
> +                       break;
> +               default:
> +                       break;
> +               }
> +               break;
> +
> +       default:
> +               dev_err(aspeed_jtag->dev, "aspeed_jtag_run_test_idle error\n");
> +               break;
> +       }
> +
> +       /* Stay on IDLE for at least  TCK cycle */
> +       for (i = 0; i < runtest->tck; i++)
> +               aspeed_jtag_tck_cycle(aspeed_jtag, 0, 0);
> +}
> +
> +/**
> + * aspeed_jtag_run_test_idle:
> + * JTAG reset: generates at least 9 TMS high and 1 TMS low to force
> + * devices into Run-Test/Idle State.
> + */
> +static int aspeed_jtag_idle(struct jtag *jtag,
> +                           struct jtag_run_test_idle *runtest)
> +{
> +       struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
> +
> +       dev_dbg(aspeed_jtag->dev, "aspeed_jtag runtest, status:%d, mode:%s, state:%s, reset:%d, tck:%d\n",
> +               aspeed_jtag->status,
> +               aspeed_jtag->mode & JTAG_XFER_HW_MODE ? "HW" : "SW",
> +               end_status_str[runtest->endstate], runtest->reset,
> +               runtest->tck);
> +
> +       if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) {
> +               aspeed_jtag_run_test_idle_sw(aspeed_jtag, runtest);
> +               return 0;
> +       }
> +
> +       /* Disable sw mode */
> +       aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW);
> +       /* x TMS high + 1 TMS low */
> +       if (runtest->reset)
> +               aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_CTL_ENG_EN |
> +                                 ASPEED_JTAG_CTL_ENG_OUT_EN |
> +                                 ASPEED_JTAG_CTL_FORCE_TMS, ASPEED_JTAG_CTRL);
> +       else
> +               aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_EC_GO_IDLE,
> +                                 ASPEED_JTAG_EC);
> +
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
> +                         ASPEED_JTAG_SW_MODE_TDIO, ASPEED_JTAG_SW);
> +
> +       aspeed_jtag->status = JTAG_STATE_IDLE;
> +       return 0;
> +}
> +
> +static void aspeed_jtag_xfer_sw(struct aspeed_jtag *aspeed_jtag,
> +                               struct jtag_xfer *xfer, unsigned long *data)
> +{
> +       unsigned long remain_xfer = xfer->length;
> +       unsigned long shift_bits = 0;
> +       unsigned long index = 0;
> +       unsigned long tdi;
> +       char          tdo;
> +
> +       if (xfer->direction == JTAG_READ_XFER)
> +               tdi = UINT_MAX;
> +       else
> +               tdi = data[index];
> +
> +       while (remain_xfer > 1) {
> +               tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 0,
> +                                           tdi & ASPEED_JTAG_DATA_MSB);
> +               data[index] |= tdo << (shift_bits %
> +                                           ASPEED_JTAG_DATA_CHUNK_SIZE);
> +
> +               tdi >>= 1;
> +               shift_bits++;
> +               remain_xfer--;
> +
> +               if (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE == 0) {
> +                       dev_dbg(aspeed_jtag->dev, "R/W data[%lu]:%lx\n",
> +                               index, data[index]);
> +
> +                       tdo = 0;
> +                       index++;
> +
> +                       if (xfer->direction == JTAG_READ_XFER)
> +                               tdi = UINT_MAX;
> +                       else
> +                               tdi = data[index];
> +               }
> +       }
> +
> +       tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 1, tdi & ASPEED_JTAG_DATA_MSB);
> +       data[index] |= tdo << (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE);
> +}
> +
> +static void aspeed_jtag_xfer_push_data(struct aspeed_jtag *aspeed_jtag,
> +                                      enum jtag_xfer_type type, u32 bits_len)
> +{
> +       dev_dbg(aspeed_jtag->dev, "shift bits %d\n", bits_len);
> +
> +       if (type == JTAG_SIR_XFER) {
> +               aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_IOUT_LEN(bits_len),
> +                                 ASPEED_JTAG_CTRL);
> +               aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_DOUT_LEN(bits_len) |
> +                                 ASPEED_JTAG_CTL_INST_EN, ASPEED_JTAG_CTRL);
> +       } else {
> +               aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_DOUT_LEN(bits_len),
> +                                 ASPEED_JTAG_CTRL);
> +               aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_DOUT_LEN(bits_len) |
> +                                 ASPEED_JTAG_CTL_DATA_EN, ASPEED_JTAG_CTRL);
> +       }
> +}
> +
> +static void aspeed_jtag_xfer_push_data_last(struct aspeed_jtag *aspeed_jtag,
> +                                           enum jtag_xfer_type type,
> +                                           u32 shift_bits,
> +                                           enum jtag_endstate endstate)
> +{
> +       if (endstate != JTAG_STATE_IDLE) {
> +               if (type == JTAG_SIR_XFER) {
> +                       dev_dbg(aspeed_jtag->dev, "IR Keep Pause\n");
> +
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_IOUT_LEN(shift_bits),
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_IOUT_LEN(shift_bits) |
> +                                         ASPEED_JTAG_CTL_INST_EN,
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_wait_instruction_pause(aspeed_jtag);
> +               } else {
> +                       dev_dbg(aspeed_jtag->dev, "DR Keep Pause\n");
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_DOUT_LEN(shift_bits) |
> +                                         ASPEED_JTAG_CTL_DR_UPDATE,
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_DOUT_LEN(shift_bits) |
> +                                         ASPEED_JTAG_CTL_DR_UPDATE |
> +                                         ASPEED_JTAG_CTL_DATA_EN,
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_wait_data_pause_complete(aspeed_jtag);
> +               }
> +       } else {
> +               if (type == JTAG_SIR_XFER) {
> +                       dev_dbg(aspeed_jtag->dev, "IR go IDLE\n");
> +
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_IOUT_LEN(shift_bits) |
> +                                         ASPEED_JTAG_CTL_LASPEED_INST,
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_IOUT_LEN(shift_bits) |
> +                                         ASPEED_JTAG_CTL_LASPEED_INST |
> +                                         ASPEED_JTAG_CTL_INST_EN,
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_wait_instruction_complete(aspeed_jtag);
> +               } else {
> +                       dev_dbg(aspeed_jtag->dev, "DR go IDLE\n");
> +
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_DOUT_LEN(shift_bits) |
> +                                         ASPEED_JTAG_CTL_LASPEED_DATA,
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_write(aspeed_jtag,
> +                                         ASPEED_JTAG_DOUT_LEN(shift_bits) |
> +                                         ASPEED_JTAG_CTL_LASPEED_DATA |
> +                                         ASPEED_JTAG_CTL_DATA_EN,
> +                                         ASPEED_JTAG_CTRL);
> +                       aspeed_jtag_wait_data_complete(aspeed_jtag);
> +               }
> +       }
> +}
> +
> +static void aspeed_jtag_xfer_hw(struct aspeed_jtag *aspeed_jtag,
> +                               struct jtag_xfer *xfer, unsigned long *data)
> +{
> +       unsigned long remain_xfer = xfer->length;
> +       unsigned long index = 0;
> +       char shift_bits;
> +       u32 data_reg;
> +
> +       data_reg = xfer->type == JTAG_SIR_XFER ?
> +                  ASPEED_JTAG_INST : ASPEED_JTAG_DATA;
> +       while (remain_xfer) {
> +               if (xfer->direction == JTAG_WRITE_XFER) {
> +                       dev_dbg(aspeed_jtag->dev, "W dr->dr_data[%lu]:%lx\n",
> +                               index, data[index]);
> +
> +                       aspeed_jtag_write(aspeed_jtag, data[index], data_reg);
> +               } else {
> +                       aspeed_jtag_write(aspeed_jtag, 0, data_reg);
> +               }
> +
> +               if (remain_xfer > ASPEED_JTAG_DATA_CHUNK_SIZE) {
> +                       shift_bits = ASPEED_JTAG_DATA_CHUNK_SIZE;
> +
> +                       /*
> +                        * Read bytes were not equals to column length
> +                        * and go to Pause-DR
> +                        */
> +                       aspeed_jtag_xfer_push_data(aspeed_jtag, xfer->type,
> +                                                  shift_bits);
> +               } else {
> +                       /*
> +                        * Read bytes equals to column length =>
> +                        * Update-DR
> +                        */
> +                       shift_bits = remain_xfer;
> +                       aspeed_jtag_xfer_push_data_last(aspeed_jtag, xfer->type,
> +                                                       shift_bits,
> +                                                       xfer->endstate);
> +               }
> +
> +               if (xfer->direction == JTAG_READ_XFER) {
> +                       if (shift_bits < ASPEED_JTAG_DATA_CHUNK_SIZE) {
> +                               data[index] = aspeed_jtag_read(aspeed_jtag,
> +                                                              data_reg);
> +
> +                               data[index] >>= ASPEED_JTAG_DATA_CHUNK_SIZE -
> +                                                               shift_bits;
> +                       } else {
> +                               data[index] = aspeed_jtag_read(aspeed_jtag,
> +                                                              data_reg);
> +                       }
> +                       dev_dbg(aspeed_jtag->dev, "R dr->dr_data[%lu]:%lx\n",
> +                               index, data[index]);
> +               }
> +
> +               remain_xfer = remain_xfer - shift_bits;
> +               index++;
> +               dev_dbg(aspeed_jtag->dev, "remain_xfer %lu\n", remain_xfer);
> +       }
> +}
> +
> +static int aspeed_jtag_xfer(struct jtag *jtag, struct jtag_xfer *xfer,
> +                           u8 *xfer_data)
> +{
> +       static const u8 sm_update_shiftir[] = {1, 1, 0, 0};
> +       static const u8 sm_update_shiftdr[] = {1, 0, 0};
> +       static const u8 sm_pause_idle[] = {1, 1, 0};
> +       static const u8 sm_pause_update[] = {1, 1};
> +       struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
> +       unsigned long *data = (unsigned long *)xfer_data;
> +       unsigned long remain_xfer = xfer->length;
> +       unsigned long offset;
> +       char dbg_str[256];
> +       int pos = 0;
> +       int i;
> +
> +       for (offset = 0, i = 0; offset < xfer->length;
> +                       offset += ASPEED_JTAG_DATA_CHUNK_SIZE, i++) {
> +               pos += snprintf(&dbg_str[pos], sizeof(dbg_str) - pos,
> +                               "0x%08lx ", data[i]);
> +       }
> +
> +       dev_dbg(aspeed_jtag->dev, "aspeed_jtag %s %s xfer, mode:%s, END:%d, len:%lu, TDI[%s]\n",
> +               xfer->type == JTAG_SIR_XFER ? "SIR" : "SDR",
> +               xfer->direction == JTAG_READ_XFER ? "READ" : "WRITE",
> +               aspeed_jtag->mode & JTAG_XFER_HW_MODE ? "HW" : "SW",
> +               xfer->endstate, remain_xfer, dbg_str);
> +
> +       if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) {
> +               /* SW mode */
> +               aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
> +                                 ASPEED_JTAG_SW_MODE_TDIO, ASPEED_JTAG_SW);
> +
> +               if (aspeed_jtag->status != JTAG_STATE_IDLE) {
> +                       /*IR/DR Pause->Exit2 IR / DR->Update IR /DR */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_pause_update,
> +                                            sizeof(sm_pause_update));
> +               }
> +
> +               if (xfer->type == JTAG_SIR_XFER)
> +                       /* ->IRSCan->CapIR->ShiftIR */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_update_shiftir,
> +                                            sizeof(sm_update_shiftir));
> +               else
> +                       /* ->DRScan->DRCap->DRShift */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_update_shiftdr,
> +                                            sizeof(sm_update_shiftdr));
> +
> +               aspeed_jtag_xfer_sw(aspeed_jtag, xfer, data);
> +
> +               /* DIPause/DRPause */
> +               aspeed_jtag_tck_cycle(aspeed_jtag, 0, 0);
> +
> +               if (xfer->endstate == JTAG_STATE_IDLE) {
> +                       /* ->DRExit2->DRUpdate->IDLE */
> +                       aspeed_jtag_sm_cycle(aspeed_jtag, sm_pause_idle,
> +                                            sizeof(sm_pause_idle));
> +               }
> +       } else {
> +               /* hw mode */
> +               aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW);
> +               aspeed_jtag_xfer_hw(aspeed_jtag, xfer, data);
> +       }
> +
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
> +                         ASPEED_JTAG_SW_MODE_TDIO, ASPEED_JTAG_SW);
> +       aspeed_jtag->status = xfer->endstate;
> +       return 0;
> +}
> +
> +static int aspeed_jtag_status_get(struct jtag *jtag, u32 *status)
> +{
> +       struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
> +
> +       *status = aspeed_jtag->status;
> +       return 0;
> +}
> +
> +static irqreturn_t aspeed_jtag_interrupt(s32 this_irq, void *dev_id)
> +{
> +       struct aspeed_jtag *aspeed_jtag = dev_id;
> +       irqreturn_t ret;
> +       u32 status;
> +
> +       status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR);
> +       dev_dbg(aspeed_jtag->dev, "status %x\n", status);
> +
> +       if (status & ASPEED_JTAG_ISR_INT_MASK) {
> +               aspeed_jtag_write(aspeed_jtag,
> +                                 (status & ASPEED_JTAG_ISR_INT_MASK)
> +                                 | (status & ASPEED_JTAG_ISR_INT_EN_MASK),
> +                                 ASPEED_JTAG_ISR);
> +               aspeed_jtag->flag |= status & ASPEED_JTAG_ISR_INT_MASK;
> +       }
> +
> +       if (aspeed_jtag->flag) {
> +               wake_up_interruptible(&aspeed_jtag->jtag_wq);
> +               ret = IRQ_HANDLED;
> +       } else {
> +               dev_err(aspeed_jtag->dev, "aspeed_jtag irq status:%x\n",
> +                       status);
> +               ret = IRQ_NONE;
> +       }
> +       return ret;
> +}
> +
> +int aspeed_jtag_init(struct platform_device *pdev,
> +                    struct aspeed_jtag *aspeed_jtag)
> +{
> +       struct resource *res;
> +       int err;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       aspeed_jtag->reg_base = devm_ioremap_resource(aspeed_jtag->dev, res);
> +       if (IS_ERR(aspeed_jtag->reg_base))
> +               return -ENOMEM;
> +
> +       aspeed_jtag->pclk = devm_clk_get(aspeed_jtag->dev, NULL);
> +       if (IS_ERR(aspeed_jtag->pclk)) {
> +               dev_err(aspeed_jtag->dev, "devm_clk_get failed\n");
> +               return PTR_ERR(aspeed_jtag->pclk);
> +       }
> +
> +       clk_prepare_enable(aspeed_jtag->pclk);
> +
> +       aspeed_jtag->irq = platform_get_irq(pdev, 0);
> +       if (aspeed_jtag->irq < 0) {
> +               dev_err(aspeed_jtag->dev, "no irq specified\n");
> +               err = -ENOENT;
> +               goto clk_unprep;
> +       }
> +
> +       /* Enable clock */
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_CTL_ENG_EN |
> +                         ASPEED_JTAG_CTL_ENG_OUT_EN, ASPEED_JTAG_CTRL);
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
> +                         ASPEED_JTAG_SW_MODE_TDIO, ASPEED_JTAG_SW);
> +
> +       err = devm_request_irq(aspeed_jtag->dev, aspeed_jtag->irq,
> +                              aspeed_jtag_interrupt, 0,
> +                              "aspeed-jtag", aspeed_jtag);
> +       if (err) {
> +               dev_err(aspeed_jtag->dev, "aspeed_jtag unable to get IRQ");
> +               goto clk_unprep;
> +       }
> +       dev_dbg(&pdev->dev, "aspeed_jtag:IRQ %d.\n", aspeed_jtag->irq);
> +
> +       aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_ISR_INST_PAUSE |
> +                         ASPEED_JTAG_ISR_INST_COMPLETE |
> +                         ASPEED_JTAG_ISR_DATA_PAUSE |
> +                         ASPEED_JTAG_ISR_DATA_COMPLETE |
> +                         ASPEED_JTAG_ISR_INST_PAUSE_EN |
> +                         ASPEED_JTAG_ISR_INST_COMPLETE_EN |
> +                         ASPEED_JTAG_ISR_DATA_PAUSE_EN |
> +                         ASPEED_JTAG_ISR_DATA_COMPLETE_EN,
> +                         ASPEED_JTAG_ISR);
> +
> +       aspeed_jtag->flag = 0;
> +       aspeed_jtag->mode = 0;
> +       init_waitqueue_head(&aspeed_jtag->jtag_wq);
> +       return 0;
> +
> +clk_unprep:
> +       clk_disable_unprepare(aspeed_jtag->pclk);
> +       return err;
> +}
> +
> +int aspeed_jtag_deinit(struct platform_device *pdev,
> +                      struct aspeed_jtag *aspeed_jtag)
> +{
> +       aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_ISR);
> +       /* Disable clock */
> +       aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL);
> +       clk_disable_unprepare(aspeed_jtag->pclk);
> +       return 0;
> +}
> +
> +static const struct jtag_ops aspeed_jtag_ops = {
> +       .freq_get = aspeed_jtag_freq_get,
> +       .freq_set = aspeed_jtag_freq_set,
> +       .status_get = aspeed_jtag_status_get,
> +       .idle = aspeed_jtag_idle,
> +       .xfer = aspeed_jtag_xfer,
> +       .mode_set = aspeed_jtag_mode_set
> +};
> +
> +static int aspeed_jtag_probe(struct platform_device *pdev)
> +{
> +       struct aspeed_jtag *aspeed_jtag;
> +       struct jtag *jtag;
> +       int err;
> +
> +       if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,aspeed-jtag"))

Should this be "aspeed,ast2400-jtag"/"aspeed,ast2500-jtag" as
specified in the compatible string below?

> +               return -ENOMEM;
> +
> +       jtag = jtag_alloc(sizeof(*aspeed_jtag), &aspeed_jtag_ops);
> +       if (!jtag)
> +               return -ENODEV;
> +
> +       platform_set_drvdata(pdev, jtag);
> +       aspeed_jtag = jtag_priv(jtag);
> +       aspeed_jtag->dev = &pdev->dev;
> +
> +       /* Initialize device*/
> +       err = aspeed_jtag_init(pdev, aspeed_jtag);
> +       if (err)
> +               goto err_jtag_init;
> +
> +       /* Initialize JTAG core structure*/
> +       err = jtag_register(jtag);
> +       if (err)
> +               goto err_jtag_register;
> +
> +       return 0;
> +
> +err_jtag_register:
> +       aspeed_jtag_deinit(pdev, aspeed_jtag);
> +err_jtag_init:
> +       jtag_free(jtag);
> +       return err;
> +}
> +
> +static int aspeed_jtag_remove(struct platform_device *pdev)
> +{
> +       struct jtag *jtag;
> +
> +       jtag = platform_get_drvdata(pdev);
> +       aspeed_jtag_deinit(pdev, jtag_priv(jtag));
> +       jtag_unregister(jtag);
> +       jtag_free(jtag);
> +       return 0;
> +}
> +
> +static const struct of_device_id aspeed_jtag_of_match[] = {
> +       { .compatible = "aspeed,ast2400-jtag", },
> +       { .compatible = "aspeed,ast2500-jtag", },
> +       {}
> +};
> +
> +static struct platform_driver aspeed_jtag_driver = {
> +       .probe = aspeed_jtag_probe,
> +       .remove = aspeed_jtag_remove,
> +       .driver = {
> +               .name = ASPEED_JTAG_NAME,
> +               .of_match_table = aspeed_jtag_of_match,
> +       },
> +};
> +module_platform_driver(aspeed_jtag_driver);
> +
> +MODULE_AUTHOR("Oleksandr Shamray <oleksandrs@mellanox.com>");
> +MODULE_DESCRIPTION("ASPEED JTAG driver");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.1
>



-- 
Regards,
Kun

^ permalink raw reply

* Re: [RFC 0/2] of: Add whitelist
From: Frank Rowand @ 2017-11-29 22:47 UTC (permalink / raw)
  To: Alan Tull, Rob Herring, Pantelis Antoniou
  Cc: Moritz Fischer, devicetree, linux-kernel, linux-fpga
In-Reply-To: <da4c9b29-eccc-6a67-291a-73a36c1598b5@gmail.com>

On 11/29/17 04:20, Frank Rowand wrote:
> On 11/27/17 15:58, Alan Tull wrote:
>> Here's a proposal for a whitelist to lock down the dynamic device tree.
>>
>> For an overlay to be accepted, all of its targets are required to be
>> on a target node whitelist.
>>
>> Currently the only way I have to get on the whitelist is calling a
>> function to add a node.  That works for fpga regions, but I think
>> other uses will need a way of having adding specific nodes from the
>> base device tree, such as by adding a property like 'allow-overlay;'
>> or 'allow-overlay = "okay";' If that is acceptable, I could use some
>> advice on where that particular code should go.
>>
>> Alan
>>
>> Alan Tull (2):
>>   of: overlay: add whitelist
>>   fpga: of region: add of-fpga-region to whitelist
>>
>>  drivers/fpga/of-fpga-region.c |  9 ++++++
>>  drivers/of/overlay.c          | 73 +++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/of.h            | 12 +++++++
>>  3 files changed, 94 insertions(+)
>>
> 
> The plan was to use connectors to restrict where an overlay could be applied.
> I would prefer not to have multiple methods for accomplishing the same thing
> unless there is a compelling reason to do so.

Going back one level in my thinking, I don't think that having a driver mark
a node as a location where an overlay fragment can be applied is serving a
useful purpose.  Any driver, including any driver loaded as a module,
could mark a node as ok.  I don't see how this is providing any meaningful
restriction on where an overlay fragment can be applied.

-Frank

^ permalink raw reply

* Re: [PATCH v4 7/8] netdev: octeon-ethernet: Add Cavium Octeon III support.
From: Andrew Lunn @ 2017-11-29 22:16 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Mark Rutland, linux-mips, devel, devicetree, netdev, David Daney,
	linux-kernel, ralf, Carlos Munoz, Rob Herring, Souptick Joarder,
	Steven J. Hill, Greg Kroah-Hartman, Florian Fainelli, James Hogan,
	David S. Miller
In-Reply-To: <20171129191138.ntlfw5fb4xacwyun@mwanda>

On Wed, Nov 29, 2017 at 10:11:38PM +0300, Dan Carpenter wrote:
> On Wed, Nov 29, 2017 at 09:37:15PM +0530, Souptick Joarder wrote:
> > >> +static int bgx_port_sgmii_set_link_speed(struct bgx_port_priv *priv, struct port_status status)
> > >> +{
> > >> +       u64     data;
> > >> +       u64     prtx;
> > >> +       u64     miscx;
> > >> +       int     timeout;
> > >> +
> > 
> > >> +
> > >> +       switch (status.speed) {
> > >> +       case 10:
> > >
> > > In my opinion, instead of hard coding the value, is it fine to use ENUM ?
> >    Similar comments applicable in other places where hard coded values are used.
> > 
> 
> 10 means 10M right?  That's not really a magic number.  It's fine.

There are also :
uapi/linux/ethtool.h:#define SPEED_10		10
uapi/linux/ethtool.h:#define SPEED_100		100
uapi/linux/ethtool.h:#define SPEED_1000		1000
uapi/linux/ethtool.h:#define SPEED_10000	10000
uapi/linux/ethtool.h:#define SPEED_100000	100000

	     Andrew

^ permalink raw reply

* Re: [PATCH] rtc: add mxc driver for i.MX53
From: Alexandre Belloni @ 2017-11-29 22:11 UTC (permalink / raw)
  To: linux-kernel-dev-QonKdJ6Bx35Wk0Htik3J/w
  Cc: Alessandro Zummo, Patrick Bruenn, Rob Herring, Mark Rutland,
	open list:REAL TIME CLOCK (RTC) SUBSYSTEM,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, Fabio Estevam, Juergen Borleis, Noel Vellemans,
	Shawn Guo, Sascha Hauer, Russell King,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20171128073927.12035-1-linux-kernel-dev-QonKdJ6Bx35Wk0Htik3J/w@public.gmane.org>

Hi,

A really quick review:

On 28/11/2017 at 08:39:27 +0100, linux-kernel-dev-QonKdJ6Bx35Wk0Htik3J/w@public.gmane.org wrote:
> From: Patrick Bruenn <p.bruenn-QonKdJ6Bx35Wk0Htik3J/w@public.gmane.org>
> 
> Neither rtc-imxdi nor rtc-mxc are compatible with i.MX53.
> Add a modernized version of mxc_v2 from here:
> http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/rtc/rtc-mxc_v2.c?h=imx_2.6.35_11.09.01
> 
> Changes to that version:
> - updated to v4.15-rc1
> - removed ioctl()
> - removed proc()
> - removed manual(redundant) enable_irq flag
> 

I'd say this doesn't add much information as this link is probably bound
to die at some point (especially seeing the NXP/Qualcomm/Broadcom
story).

> Signed-off-by: Patrick Bruenn <p.bruenn-QonKdJ6Bx35Wk0Htik3J/w@public.gmane.org>
> 
> ---
> 
> Open issues:
> - driver naming, should it be merged with rtc-mxc.c ?

This seems different enough to be a separate driver.

> - document DT binding "fsl,imx53-rtc" accordingly

Yes, this has to be documented in a previous patch

> - Should unused defines be removed or kept for someone else to be
>   useful?

I don't care much, either are fine but the less lines, the easier the
reviews.

> - Is the use of __raw_readl/writel() correct? Should it be replaced with
>   readl/writel()?

The __raw version will not work if someone is running a BE kernel so
they should be moved to the _relaxed version or the usual readl/writel.

> - suspend/resume() seems different to existing rtc-mxc.c, should I apply
>   the pattern from rtc-mxc.c?

If you mean using SIMPLE_DEV_PM_OPS, yes, you should do that.

> - On Shawns tree imx53.dtsi has been reverted already[1][2]. Should I split
>   the imx53.dtsi change into a separate patch based on his tree? Or can
>   we still stop the full revert and just remove the imx25-rtc compatible?
>   I am not in a hurry, so we could just wait until the revert landed in
>   Linus tree. Whatever you think is best.
> 

I'm not taking DT changes through the RTC tree so it should be in a
separate patch that will go through Shawn's tree

You should also use checkpatch --strict, most of the warnings are
correct.


> [1] https://www.spinics.net/lists/arm-kernel/msg617113.html
> [2] commit ee76f7729babd2700afd6f3874449d8084dd85ea
> 
> To: Alessandro Zummo <a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org>
> To: Alexandre Belloni <alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
> Cc: linux-rtc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org (open list)
> Cc: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
> Cc: Juergen Borleis <jbe-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: Noel Vellemans <Noel.Vellemans-8UENEgx6w+makBO8gow8eQ@public.gmane.org>
> Cc: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Sascha Hauer <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
> Cc: Russell King <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org> (maintainer:ARM PORT)
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
> ---
>  arch/arm/boot/dts/imx53.dtsi |   2 +-
>  drivers/rtc/Makefile         |   1 +
>  drivers/rtc/rtc-mxc_v2.c     | 531 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 533 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/rtc/rtc-mxc_v2.c
> 
> diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
> index 589a67c5f796..3d1a55e11ea8 100644
> --- a/arch/arm/boot/dts/imx53.dtsi
> +++ b/arch/arm/boot/dts/imx53.dtsi
> @@ -434,7 +434,7 @@
>  			};
>  
>  			srtc: srtc@53fa4000 {
> -				compatible = "fsl,imx53-rtc", "fsl,imx25-rtc";
> +				compatible = "fsl,imx53-rtc";
>  				reg = <0x53fa4000 0x4000>;
>  				interrupts = <24>;
>  				interrupt-parent = <&tzic>;
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index f2f50c11dc38..fb3dc458c185 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -106,6 +106,7 @@ obj-$(CONFIG_RTC_DRV_MT6397)	+= rtc-mt6397.o
>  obj-$(CONFIG_RTC_DRV_MT7622)	+= rtc-mt7622.o
>  obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
>  obj-$(CONFIG_RTC_DRV_MXC)	+= rtc-mxc.o
> +obj-$(CONFIG_RTC_DRV_MXC)	+= rtc-mxc_v2.o

This definitively needs a different Kconfig symbol.

>  obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o
>  obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
>  obj-$(CONFIG_RTC_DRV_OPAL)	+= rtc-opal.o
> diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c
> new file mode 100644
> index 000000000000..5049b521b38e
> --- /dev/null
> +++ b/drivers/rtc/rtc-mxc_v2.c
> @@ -0,0 +1,531 @@

I think SPDX identifier will soon be required on new files, please add
one.

> +/*
> + * Copyright (C) 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + */
> +
> +/*
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +/*
> + * Implementation based on rtc-ds1553.c
> + */
> +
> +/*!
> + * @defgroup RTC Real Time Clock (RTC) Driver for i.MX53
> + */
> +/*!
> + * @file rtc-mxc_v2.c
> + * @brief Real Time Clock interface
> + *
> + * This file contains Real Time Clock interface for Linux.
> + *
> + * @ingroup RTC
> + */
> +

Is that comment really useful?

> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/rtc.h>
> +#include <linux/module.h>
> +#include <linux/fs.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/uaccess.h>
> +#include <linux/io.h>

This should be in alphabetical order

> +//#include <linux/mxc_srtc.h>

This is not useful

> +#define RTC_READ_TIME_47BIT	_IOR('p', 0x20, unsigned long long)
> +/* blocks until LPSCMR is set, returns difference */
> +#define RTC_WAIT_TIME_SET	_IOR('p', 0x21, int64_t)
> +

Those ioctls are not used.

> +#define SRTC_LPSCLR_LLPSC_LSH	17	/* start bit for LSB time value */
> +
> +#define SRTC_LPPDR_INIT       0x41736166	/* init for glitch detect */
> +
> +#define SRTC_LPCR_SWR_LP      (1 << 0)	/* lp software reset */
> +#define SRTC_LPCR_EN_LP       (1 << 3)	/* lp enable */
> +#define SRTC_LPCR_WAE         (1 << 4)	/* lp wakeup alarm enable */
> +#define SRTC_LPCR_SAE         (1 << 5)	/* lp security alarm enable */
> +#define SRTC_LPCR_SI          (1 << 6)	/* lp security interrupt enable */
> +#define SRTC_LPCR_ALP         (1 << 7)	/* lp alarm flag */
> +#define SRTC_LPCR_LTC         (1 << 8)	/* lp lock time counter */
> +#define SRTC_LPCR_LMC         (1 << 9)	/* lp lock monotonic counter */
> +#define SRTC_LPCR_SV          (1 << 10)	/* lp security violation */
> +#define SRTC_LPCR_NSA         (1 << 11)	/* lp non secure access */
> +#define SRTC_LPCR_NVEIE       (1 << 12)	/* lp non valid state exit int en */
> +#define SRTC_LPCR_IEIE        (1 << 13)	/* lp init state exit int enable */
> +#define SRTC_LPCR_NVE         (1 << 14)	/* lp non valid state exit bit */
> +#define SRTC_LPCR_IE          (1 << 15)	/* lp init state exit bit */
> +
> +#define SRTC_LPCR_ALL_INT_EN (SRTC_LPCR_WAE | SRTC_LPCR_SAE | \
> +			      SRTC_LPCR_SI | SRTC_LPCR_ALP | \
> +			      SRTC_LPCR_NVEIE | SRTC_LPCR_IEIE)
> +
> +#define SRTC_LPSR_TRI         (1 << 0)	/* lp time read invalidate */
> +#define SRTC_LPSR_PGD         (1 << 1)	/* lp power supply glitc detected */
> +#define SRTC_LPSR_CTD         (1 << 2)	/* lp clock tampering detected */
> +#define SRTC_LPSR_ALP         (1 << 3)	/* lp alarm flag */
> +#define SRTC_LPSR_MR          (1 << 4)	/* lp monotonic counter rollover */
> +#define SRTC_LPSR_TR          (1 << 5)	/* lp time rollover */
> +#define SRTC_LPSR_EAD         (1 << 6)	/* lp external alarm detected */
> +#define SRTC_LPSR_IT0         (1 << 7)	/* lp IIM throttle */
> +#define SRTC_LPSR_IT1         (1 << 8)
> +#define SRTC_LPSR_IT2         (1 << 9)
> +#define SRTC_LPSR_SM0         (1 << 10)	/* lp security mode */
> +#define SRTC_LPSR_SM1         (1 << 11)
> +#define SRTC_LPSR_STATE_LP0   (1 << 12)	/* lp state */
> +#define SRTC_LPSR_STATE_LP1   (1 << 13)
> +#define SRTC_LPSR_NVES        (1 << 14)	/* lp non-valid state exit status */
> +#define SRTC_LPSR_IES         (1 << 15)	/* lp init state exit status */
> +
> +#define MAX_PIE_NUM     15
> +#define MAX_PIE_FREQ    32768
> +#define MIN_PIE_FREQ	1
> +
> +#define SRTC_PI0         (1 << 0)
> +#define SRTC_PI1         (1 << 1)
> +#define SRTC_PI2         (1 << 2)
> +#define SRTC_PI3         (1 << 3)
> +#define SRTC_PI4         (1 << 4)
> +#define SRTC_PI5         (1 << 5)
> +#define SRTC_PI6         (1 << 6)
> +#define SRTC_PI7         (1 << 7)
> +#define SRTC_PI8         (1 << 8)
> +#define SRTC_PI9         (1 << 9)
> +#define SRTC_PI10        (1 << 10)
> +#define SRTC_PI11        (1 << 11)
> +#define SRTC_PI12        (1 << 12)
> +#define SRTC_PI13        (1 << 13)
> +#define SRTC_PI14        (1 << 14)
> +#define SRTC_PI15        (1 << 15)
> +
> +#define PIT_ALL_ON      (SRTC_PI1 | SRTC_PI2 | SRTC_PI3 | \
> +			SRTC_PI4 | SRTC_PI5 | SRTC_PI6 | SRTC_PI7 | \
> +			SRTC_PI8 | SRTC_PI9 | SRTC_PI10 | SRTC_PI11 | \
> +			SRTC_PI12 | SRTC_PI13 | SRTC_PI14 | SRTC_PI15)
> +
> +#define SRTC_SWR_HP      (1 << 0)	/* hp software reset */
> +#define SRTC_EN_HP       (1 << 3)	/* hp enable */
> +#define SRTC_TS          (1 << 4)	/* time synchronize hp with lp */
> +
> +#define SRTC_IE_AHP      (1 << 16)	/* Alarm HP Interrupt Enable bit */
> +#define SRTC_IE_WDHP     (1 << 18)	/* Write Done HP Interrupt Enable bit */
> +#define SRTC_IE_WDLP     (1 << 19)	/* Write Done LP Interrupt Enable bit */
> +
> +#define SRTC_ISR_AHP     (1 << 16)	/* interrupt status: alarm hp */
> +#define SRTC_ISR_WDHP    (1 << 18)	/* interrupt status: write done hp */
> +#define SRTC_ISR_WDLP    (1 << 19)	/* interrupt status: write done lp */
> +#define SRTC_ISR_WPHP    (1 << 20)	/* interrupt status: write pending hp */
> +#define SRTC_ISR_WPLP    (1 << 21)	/* interrupt status: write pending lp */
> +
> +#define SRTC_LPSCMR	0x00	/* LP Secure Counter MSB Reg */
> +#define SRTC_LPSCLR	0x04	/* LP Secure Counter LSB Reg */
> +#define SRTC_LPSAR	0x08	/* LP Secure Alarm Reg */
> +#define SRTC_LPSMCR	0x0C	/* LP Secure Monotonic Counter Reg */
> +#define SRTC_LPCR	0x10	/* LP Control Reg */
> +#define SRTC_LPSR	0x14	/* LP Status Reg */
> +#define SRTC_LPPDR	0x18	/* LP Power Supply Glitch Detector Reg */
> +#define SRTC_LPGR	0x1C	/* LP General Purpose Reg */
> +#define SRTC_HPCMR	0x20	/* HP Counter MSB Reg */
> +#define SRTC_HPCLR	0x24	/* HP Counter LSB Reg */
> +#define SRTC_HPAMR	0x28	/* HP Alarm MSB Reg */
> +#define SRTC_HPALR	0x2C	/* HP Alarm LSB Reg */
> +#define SRTC_HPCR	0x30	/* HP Control Reg */
> +#define SRTC_HPISR	0x34	/* HP Interrupt Status Reg */
> +#define SRTC_HPIENR	0x38	/* HP Interrupt Enable Reg */
> +
> +#define SRTC_SECMODE_MASK	0x3	/* the mask of SRTC security mode */
> +#define SRTC_SECMODE_LOW	0x0	/* Low Security */
> +#define SRTC_SECMODE_MED	0x1	/* Medium Security */
> +#define SRTC_SECMODE_HIGH	0x2	/* High Security */
> +#define SRTC_SECMODE_RESERVED	0x3	/* Reserved */
> +
> +struct rtc_drv_data {
> +	struct rtc_device *rtc;
> +	void __iomem *ioaddr;
> +	int irq;
> +	struct clk *clk;
> +};
> +
> +static DEFINE_SPINLOCK(rtc_lock);
> +

Shouldn't that lock be part of rtc_drv_data?

> +/*!
> + * This function does write synchronization for writes to the lp srtc block.
> + * To take care of the asynchronous CKIL clock, all writes from the IP domain
> + * will be synchronized to the CKIL domain.
> + */
> +static inline void rtc_write_sync_lp(void __iomem *ioaddr)
> +{
> +	unsigned int i, count;
> +	/* Wait for 3 CKIL cycles */
> +	for (i = 0; i < 3; i++) {
> +		count = readl(ioaddr + SRTC_LPSCLR);
> +		while ((readl(ioaddr + SRTC_LPSCLR)) == count)
> +			;
> +	}
> +}
> +
> +/*!
> + * This function updates the RTC alarm registers and then clears all the
> + * interrupt status bits.
> + *
> + * @param  alrm         the new alarm value to be updated in the RTC
> + *
> + * @return  0 if successful; non-zero otherwise.
> + */
> +static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
> +{
> +	struct rtc_drv_data *pdata = dev_get_drvdata(dev);
> +	void __iomem *ioaddr = pdata->ioaddr;
> +	struct rtc_time alarm_tm, now_tm;
> +	unsigned long now, time;
> +	int ret;
> +
> +	now = __raw_readl(ioaddr + SRTC_LPSCMR);
> +	rtc_time_to_tm(now, &now_tm);
> +
> +	alarm_tm.tm_year = now_tm.tm_year;
> +	alarm_tm.tm_mon = now_tm.tm_mon;
> +	alarm_tm.tm_mday = now_tm.tm_mday;
> +
> +	alarm_tm.tm_hour = alrm->tm_hour;
> +	alarm_tm.tm_min = alrm->tm_min;
> +	alarm_tm.tm_sec = alrm->tm_sec;
> +
> +	rtc_tm_to_time(&now_tm, &now);
> +	rtc_tm_to_time(&alarm_tm, &time);
> +
> +	if (time < now) {
> +		time += 60 * 60 * 24;
> +		rtc_time_to_tm(time, &alarm_tm);
> +	}
> +	ret = rtc_tm_to_time(&alarm_tm, &time);
> +
> +	__raw_writel(time, ioaddr + SRTC_LPSAR);
> +
> +	/* clear alarm interrupt status bit */
> +	__raw_writel(SRTC_LPSR_ALP, ioaddr + SRTC_LPSR);
> +
> +	return ret;
> +}
> +
> +/*!
> + * This function is the RTC interrupt service routine.
> + *
> + * @param  irq          RTC IRQ number
> + * @param  dev_id       device ID which is not used
> + *
> + * @return IRQ_HANDLED as defined in the include/linux/interrupt.h file.
> + */
> +static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
> +{
> +	struct platform_device *pdev = dev_id;
> +	struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
> +	void __iomem *ioaddr = pdata->ioaddr;
> +	u32 lp_status, lp_cr;
> +	u32 events = 0;
> +
> +	lp_status = __raw_readl(ioaddr + SRTC_LPSR);
> +	lp_cr = __raw_readl(ioaddr + SRTC_LPCR);
> +
> +	/* update irq data & counter */
> +	if (lp_status & SRTC_LPSR_ALP) {
> +		if (lp_cr & SRTC_LPCR_ALP)
> +			events |= (RTC_AF | RTC_IRQF);
> +
> +		/* disable further lp alarm interrupts */
> +		lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
> +	}
> +
> +	/* Update interrupt enables */
> +	__raw_writel(lp_cr, ioaddr + SRTC_LPCR);
> +
> +	/* clear interrupt status */
> +	__raw_writel(lp_status, ioaddr + SRTC_LPSR);
> +
> +	rtc_write_sync_lp(ioaddr);
> +	rtc_update_irq(pdata->rtc, 1, events);
> +	return IRQ_HANDLED;
> +}
> +
> +/*!
> + * This function reads the current RTC time into tm in Gregorian date.
> + *
> + * @param  tm           contains the RTC time value upon return
> + *
> + * @return  0 if successful; non-zero otherwise.
> + */
> +static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct rtc_drv_data *pdata = dev_get_drvdata(dev);
> +	time_t now = readl(pdata->ioaddr + SRTC_LPSCMR);
> +
> +	rtc_time_to_tm(now, tm);
> +	return rtc_valid_tm(tm);
> +}
> +
> +/*!
> + * This function sets the internal RTC time based on tm in Gregorian date.
> + *
> + * @param  tm           the time value to be set in the RTC
> + *
> + * @return  0 if successful; non-zero otherwise.
> + */
> +static int mxc_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct rtc_drv_data *pdata = dev_get_drvdata(dev);
> +	time64_t time = rtc_tm_to_time64(tm);
> +
> +	if (time > UINT_MAX) {
> +		dev_warn(dev, "time_t has overflow\n");
> +	}
> +
> +	writel(time, pdata->ioaddr + SRTC_LPSCMR);
> +	rtc_write_sync_lp(pdata->ioaddr);
> +	return 0;
> +}
> +
> +/*!
> + * This function reads the current alarm value into the passed in \b alrm
> + * argument. It updates the \b alrm's pending field value based on the whether
> + * an alarm interrupt occurs or not.
> + *
> + * @param  alrm         contains the RTC alarm value upon return
> + *
> + * @return  0 if successful; non-zero otherwise.
> + */
> +static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct rtc_drv_data *pdata = dev_get_drvdata(dev);
> +	void __iomem *ioaddr = pdata->ioaddr;
> +
> +	rtc_time_to_tm(__raw_readl(ioaddr + SRTC_LPSAR), &alrm->time);
> +	alrm->pending =
> +	    ((__raw_readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_ALP) != 0) ? 1 : 0;
> +
> +	return 0;
> +}
> +
> +static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
> +{
> +	struct rtc_drv_data *pdata = dev_get_drvdata(dev);
> +	unsigned long lock_flags = 0;
> +	u32 lp_cr;
> +
> +	spin_lock_irqsave(&rtc_lock, lock_flags);
> +	lp_cr = __raw_readl(pdata->ioaddr + SRTC_LPCR);
> +
> +	if (enable)
> +		lp_cr |= (SRTC_LPCR_ALP | SRTC_LPCR_WAE);
> +	else
> +		lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
> +
> +	__raw_writel(lp_cr, pdata->ioaddr + SRTC_LPCR);
> +	spin_unlock_irqrestore(&rtc_lock, lock_flags);
> +	return 0;
> +}
> +
> +/*!
> + * This function sets the RTC alarm based on passed in alrm.
> + *
> + * @param  alrm         the alarm value to be set in the RTC
> + *
> + * @return  0 if successful; non-zero otherwise.
> + */
> +static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct rtc_drv_data *pdata = dev_get_drvdata(dev);
> +	void __iomem *ioaddr = pdata->ioaddr;
> +	int ret;
> +
> +	ret = rtc_update_alarm(dev, &alrm->time);
> +	if (!ret)
> +		mxc_rtc_alarm_irq_enable(dev, alrm->enabled);
> +
> +	rtc_write_sync_lp(ioaddr);
> +	return ret;
> +}
> +
> +/*!
> + * The RTC driver structure
> + */
> +static const struct rtc_class_ops mxc_rtc_ops = {
> +	.read_time = mxc_rtc_read_time,
> +	.set_time = mxc_rtc_set_time,
> +	.read_alarm = mxc_rtc_read_alarm,
> +	.set_alarm = mxc_rtc_set_alarm,
> +	.alarm_irq_enable = mxc_rtc_alarm_irq_enable,
> +};
> +
> +/*! MXC RTC Power management control */

This comment is probably wrong ;)

> +static int mxc_rtc_probe(struct platform_device *pdev)
> +{
> +	struct timespec tv;
> +	struct resource *res;
> +	struct rtc_drv_data *pdata = NULL;
> +	void __iomem *ioaddr;
> +	int ret = 0;
> +
> +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;
> +
> +	pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(pdata->ioaddr))
> +		return PTR_ERR(pdata->ioaddr);
> +
> +	ioaddr = pdata->ioaddr;
> +
> +	pdata->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(pdata->clk)) {
> +		dev_err(&pdev->dev, "unable to get rtc clock!\n");
> +		return PTR_ERR(pdata->clk);
> +	}
> +	ret = clk_prepare_enable(pdata->clk);
> +	if (ret)
> +		return ret;
> +
> +	/* Configure and enable the RTC */
> +	pdata->irq = platform_get_irq(pdev, 0);
> +	if (pdata->irq >= 0
> +	    && devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt,
> +				IRQF_SHARED, pdev->name, pdev) < 0) {
> +		dev_warn(&pdev->dev, "interrupt not available.\n");
> +		pdata->irq = -1;
> +	}
> +
> +	if (pdata->irq >= 0)
> +		device_init_wakeup(&pdev->dev, 1);
> +
> +	/* initialize glitch detect */
> +	__raw_writel(SRTC_LPPDR_INIT, ioaddr + SRTC_LPPDR);
> +	udelay(100);
> +
> +	/* clear lp interrupt status */
> +	__raw_writel(0xFFFFFFFF, ioaddr + SRTC_LPSR);
> +	udelay(100);
> +
> +	/* move out of init state */
> +	__raw_writel((SRTC_LPCR_IE | SRTC_LPCR_NSA), ioaddr + SRTC_LPCR);
> +
> +	udelay(100);
> +
> +	while ((__raw_readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_IES) == 0)
> +		;
> +
> +	/* move out of non-valid state */
> +	__raw_writel((SRTC_LPCR_IE | SRTC_LPCR_NVE | SRTC_LPCR_NSA |
> +		      SRTC_LPCR_EN_LP), ioaddr + SRTC_LPCR);
> +
> +	udelay(100);
> +
> +	while ((__raw_readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_NVES) == 0)
> +		;
> +
> +	__raw_writel(0xFFFFFFFF, ioaddr + SRTC_LPSR);
> +	udelay(100);
> +
> +	platform_set_drvdata(pdev, pdata);
> +	pdata->rtc =
> +	    devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops,
> +				     THIS_MODULE);
> +	if (IS_ERR(pdata->rtc)) {
> +		ret = PTR_ERR(pdata->rtc);
> +		goto exit_put_clk;
> +	}
> +
> +	tv.tv_nsec = 0;
> +	tv.tv_sec = __raw_readl(ioaddr + SRTC_LPSCMR);
> +
> +	/* By default, devices should wakeup if they can */
> +	/* So srtc is set as "should wakeup" as it can */
That comment is not formatted correctly.

> +	device_init_wakeup(&pdev->dev, 1);
> +
> +	return ret;

For clarity, this has to return 0.

> +
> +exit_put_clk:
> +	clk_disable_unprepare(pdata->clk);
> +	return ret;
> +}
> +
> +static int __exit mxc_rtc_remove(struct platform_device *pdev)
> +{
> +	struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
> +
> +	clk_disable_unprepare(pdata->clk);
> +	return 0;
> +}
> +
> +/*!
> + * This function is called to save the system time delta relative to
> + * the MXC RTC when enterring a low power state. This time delta is
> + * then used on resume to adjust the system time to account for time
> + * loss while suspended.
> + *
> + * @param   pdev  not used
> + * @param   state Power state to enter.
> + *
> + * @return  The function always returns 0.
> + */
> +static int mxc_rtc_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
> +
> +	if (device_may_wakeup(&pdev->dev))
> +		enable_irq_wake(pdata->irq);
> +
> +	return 0;
> +}
> +
> +/*!
> + * This function is called to correct the system time based on the
> + * current MXC RTC time relative to the time delta saved during
> + * suspend.
> + *
> + * @param   pdev  not used
> + *
> + * @return  The function always returns 0.
> + */
> +static int mxc_rtc_resume(struct platform_device *pdev)
> +{
> +	struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
> +
> +	if (device_may_wakeup(&pdev->dev))
> +		disable_irq_wake(pdata->irq);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id mxc_ids[] = {
> +	{.compatible = "fsl,imx53-rtc",},
> +	{}
> +};
> +
> +/*!
> + * Contains pointers to the power management callback functions.
> + */
> +static struct platform_driver mxc_rtc_driver = {
> +	.driver = {
> +		   .name = "mxc_rtc_v8",

Isn't it weird to have v8 here when the file is named v2?

> +		   .of_match_table = mxc_ids,
> +		   },
> +	.probe = mxc_rtc_probe,
> +	.remove = mxc_rtc_remove,
> +	.suspend = mxc_rtc_suspend,
> +	.resume = mxc_rtc_resume,
> +};
> +
> +module_platform_driver(mxc_rtc_driver);
> +
> +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
> +MODULE_DESCRIPTION("Realtime Clock Driver (RTC)");
> +MODULE_LICENSE("GPL");
> -- 
> 2.11.0
> 
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 2/2] dt-bindings: iio: temperature: add MLX90632 device bindings
From: Crt Mori @ 2017-11-29 22:08 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Crt Mori

Add device tree bindings for MLX90632 IR temperature sensor.

Signed-off-by: Crt Mori <cmo-fc6wVz46lShBDgjK7y7TUQ@public.gmane.org>
---
 .../bindings/iio/temperature/mlx90632.txt          | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/temperature/mlx90632.txt

diff --git a/Documentation/devicetree/bindings/iio/temperature/mlx90632.txt b/Documentation/devicetree/bindings/iio/temperature/mlx90632.txt
new file mode 100644
index 000000000000..6073a5ccf9a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/temperature/mlx90632.txt
@@ -0,0 +1,28 @@
+* Melexis MLX90632 contactless Infra Red temperature sensor
+
+Link to datasheet: https://www.melexis.com/en/documents/documentation/datasheets/datasheet-mlx90632
+
+There are various applications for the Infra Red contactless temperature sensor
+and MLX90632 is most suitable for consumer applications where measured object
+temperature is in range between -20 to 200 degrees Celsius with relative error
+of measurement below 1 degree Celsius in object temperature range for
+industrial applications. Since it can operate and measure ambient temperature
+in range of -20 to 85 degrees Celsius it is suitable also for outdoor use.
+
+Be aware that electronics surrounding the sensor can increase ambient
+temperature. MLX90632 can be calibrated to reduce the housing effect via
+already existing EEPROM parameters.
+
+Since measured object emissivity effects Infra Red energy emitted, emissivity
+should be set before requesting the object temperature.
+
+Required properties:
+  - compatible: should be "melexis,mlx90632"
+  - reg: the I2C address of the sensor (default 0x3a)
+
+Example:
+
+mlx90632@02 {
+	compatible = "melexis,mlx90632";
+	reg = <0x3a>;
+};
-- 
2.15.0

^ permalink raw reply related

* Re: [PATCH 3/4] RFC: net: dsa: Add bindings for Realtek SMI DSAs
From: Andrew Lunn @ 2017-11-29 21:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Vivien Didelot, Florian Fainelli, netdev, Antti Seppälä,
	Roman Yeryomin, Colin Leitner, Gabor Juhos,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
In-Reply-To: <CACRpkdZVXgFMiHpyUqw7ONYDcq6Htn3rTMRaBJkzd6T3WtX36A@mail.gmail.com>

Hi Linus

> Just that the PHYs are on the MDIO bus inside the switch, of
> course.

I think the problem might be, you are using the DSA provided MDIO bus.
The Marvell switches has a similar setup in terms of interrupts. The
PHY interrupts appear within the switch. So i implemented an interrupt
controller, just the same as you.

The problem is, the DSA provided MDIO bus is not linked to device
tree. So you cannot have phy nodes in device tree associated to it.

What i did for the Marvell driver is that driver itself implements an
MDIO bus (two actually in some chips), and the internal or external
PHYs are placed on the switch drivers MDIO bus, rather than the DSA
MDIO bus. The switch driver MDIO bus links to an mdio node in device
tree. I can then have interrupt properties in the phys on this MDIO
bus in device tree.

What actually might make sense, is to have the DSA MDIO bus look
inside the switches device tree node and see if there is an mdio
node. If so allow dsa_switch_setup() to use of_mdiobus_register()
instead of mdiobus_register().

      Andrew

^ permalink raw reply

* Re: [PATCH 3/4] RFC: net: dsa: Add bindings for Realtek SMI DSAs
From: Florian Fainelli @ 2017-11-29 21:48 UTC (permalink / raw)
  To: Linus Walleij, Andrew Lunn
  Cc: Vivien Didelot, netdev-u79uwXL29TY76Z2rM5mHXA,
	Antti Seppälä, Roman Yeryomin, Colin Leitner,
	Gabor Juhos,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
In-Reply-To: <CACRpkdZVXgFMiHpyUqw7ONYDcq6Htn3rTMRaBJkzd6T3WtX36A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 11/29/2017 01:28 PM, Linus Walleij wrote:
> On Wed, Nov 29, 2017 at 4:56 PM, Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org> wrote:
>>> I have the phy-handle in the ethernet controller. This RTL8366RB
>>> thing is just one big PHY as far as I know.
>>
>> We don't model switches as PHYs. They are their own device type.  And
>> the internal or external PHYs are just normal PHYs in the linux
>> model. Meaning their interrupt properties goes in the PHY node in
>> device tree, as documented in the phy.txt binding documentation.
> 
> I do model the PHYs on the switch as PHYs.
> They are using the driver in drivers/phy/realtek.c.

That's good.

> 
> The interrupts are assigned to the PHYs not to the Switch.
> Just that the PHYs are on the MDIO bus inside the switch, of
> course.
> 
> The switch however provides an irqchip to demux the interrupts.
> 
> I think there is some misunderstanding in what I'm trying to do..
> 
> I have tried learning the DSA ideas by reading e.g. your paper:
> https://www.netdevconf.org/2.1/papers/distributed-switch-architecture.pdf
> 
> So I try my best to conform with these ideas.
> 
> I however have a hard time testing things since I don't really have a
> system to compare to. What would be useful is to know how
> commands like "ip" and "ifconfig" are used on a typical
> say home router.

There is a mock-up driver: drivers/net/dsa/dsa_loop.c which does not
pass any packets, but at least allows you to exercise user-space tools
and so on.
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2 19/19] ASoC: tlv320aic31xx: Add button press detection
From: Andrew F. Davis @ 2017-11-29 21:33 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel, devicetree, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

This device can optionally detect headset or microphone button presses.
Add support for this by passing this event to the jack layer.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 14 +++++++++++++-
 sound/soc/codecs/tlv320aic31xx.h |  3 ++-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 471b31be55d1..8cd27c99cb15 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1280,9 +1280,20 @@ static irqreturn_t aic31xx_irq(int irq, void *data)
 	if (value & AIC31XX_HPRSCDETECT)
 		dev_err(dev, "Short circuit on Right output is detected\n");
 
-	if (value & AIC31XX_HSPLUG) {
+	if (value & (AIC31XX_HSPLUG | AIC31XX_BUTTONPRESS)) {
 		int status = 0;
 
+		ret = regmap_read(aic31xx->regmap, AIC31XX_INTRDACFLAG2,
+				  &value);
+		if (ret) {
+			dev_err(dev, "Failed to read interrupt mask: %d\n",
+				ret);
+			return IRQ_NONE;
+		}
+
+		if (value & AIC31XX_BUTTONPRESS)
+			status |= SND_JACK_BTN_0;
+
 		ret = regmap_read(aic31xx->regmap, AIC31XX_HSDETECT, &value);
 		if (ret) {
 			dev_err(dev, "Failed to read headset type: %d\n", ret);
@@ -1395,6 +1406,7 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 
 		regmap_write(aic31xx->regmap, AIC31XX_INT1CTRL,
 			     AIC31XX_HSPLUGDET |
+			     AIC31XX_BUTTONPRESSDET |
 			     AIC31XX_SC |
 			     AIC31XX_ENGINE);
 
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
index 66c85df4d5be..7fce278eadac 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -21,7 +21,8 @@
 #define DAC31XX_BIT			BIT(3)
 
 #define AIC31XX_JACK_MASK (SND_JACK_HEADPHONE | \
-			   SND_JACK_HEADSET)
+			   SND_JACK_HEADSET | \
+			   SND_JACK_BTN_0)
 
 enum aic31xx_type {
 	AIC3100	= 0,
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 18/19] ASoC: tlv320aic31xx: Add headphone/headset detection
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd-l0cyMroinI0@public.gmane.org>

This device can detect the insertion/removal of headphones and headsets.
Enable reporting this status by enabling this interrupt and forwarding
this to upper-layers if a jack has been defined.

This jack definition and the resulting operation from a jack detection
event must currently be defined by sound card platform code until CODEC
outputs to jack mappings can be defined generically.

Signed-off-by: Andrew F. Davis <afd-l0cyMroinI0@public.gmane.org>
---
 sound/soc/codecs/tlv320aic31xx.c | 33 +++++++++++++++++++++++++++++++++
 sound/soc/codecs/tlv320aic31xx.h | 11 +++++++++++
 2 files changed, 44 insertions(+)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 094b1596f9cc..471b31be55d1 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -25,6 +25,7 @@
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <sound/core.h>
+#include <sound/jack.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -89,6 +90,7 @@ static bool aic31xx_volatile(struct device *dev, unsigned int reg)
 	case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */
 	case AIC31XX_INTRDACFLAG2:
 	case AIC31XX_INTRADCFLAG2:
+	case AIC31XX_HSDETECT:
 		return true;
 	}
 	return false;
@@ -161,6 +163,7 @@ struct aic31xx_priv {
 	struct gpio_desc *gpio_reset;
 	int micbias_vg;
 	struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
+	struct snd_soc_jack *jack;
 	unsigned int sysclk;
 	u8 p_div;
 	int rate_div_line;
@@ -1277,6 +1280,32 @@ static irqreturn_t aic31xx_irq(int irq, void *data)
 	if (value & AIC31XX_HPRSCDETECT)
 		dev_err(dev, "Short circuit on Right output is detected\n");
 
+	if (value & AIC31XX_HSPLUG) {
+		int status = 0;
+
+		ret = regmap_read(aic31xx->regmap, AIC31XX_HSDETECT, &value);
+		if (ret) {
+			dev_err(dev, "Failed to read headset type: %d\n", ret);
+			return IRQ_NONE;
+		}
+
+		switch ((value & AIC31XX_HSD_TYPE_MASK) >>
+			AIC31XX_HSD_TYPE_SHIFT) {
+		case AIC31XX_HSD_HP:
+			status |= SND_JACK_HEADPHONE;
+			break;
+		case AIC31XX_HSD_HS:
+			status |= SND_JACK_HEADSET;
+			break;
+		default:
+			break;
+		}
+
+		if (aic31xx->jack)
+			snd_soc_jack_report(aic31xx->jack, status,
+					    AIC31XX_JACK_MASK);
+	}
+
 	ret = regmap_read(aic31xx->regmap, AIC31XX_OFFLAG, &value);
 	if (ret) {
 		dev_err(dev, "Failed to read overflow flag: %d\n", ret);
@@ -1365,9 +1394,13 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 				   AIC31XX_GPIO1_FUNC_SHIFT);
 
 		regmap_write(aic31xx->regmap, AIC31XX_INT1CTRL,
+			     AIC31XX_HSPLUGDET |
 			     AIC31XX_SC |
 			     AIC31XX_ENGINE);
 
+		regmap_write(aic31xx->regmap, AIC31XX_HSDETECT,
+			     AIC31XX_HSD_ENABLE);
+
 		ret = devm_request_threaded_irq(aic31xx->dev, aic31xx->irq,
 						NULL, aic31xx_irq,
 						IRQF_ONESHOT, "aic31xx-irq",
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
index d062663f66b5..66c85df4d5be 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -20,6 +20,9 @@
 #define AIC31XX_MINIDSP_BIT		BIT(2)
 #define DAC31XX_BIT			BIT(3)
 
+#define AIC31XX_JACK_MASK (SND_JACK_HEADPHONE | \
+			   SND_JACK_HEADSET)
+
 enum aic31xx_type {
 	AIC3100	= 0,
 	AIC3110 = AIC31XX_STEREO_CLASS_D_BIT,
@@ -213,6 +216,14 @@ enum aic31xx_type {
 /* AIC31XX_DACMUTE */
 #define AIC31XX_DACMUTE_MASK		GENMASK(3, 2)
 
+/* AIC31XX_HSDETECT */
+#define AIC31XX_HSD_ENABLE		BIT(7)
+#define AIC31XX_HSD_TYPE_MASK		GENMASK(6, 5)
+#define AIC31XX_HSD_TYPE_SHIFT		5
+#define AIC31XX_HSD_NONE		0x00
+#define AIC31XX_HSD_HP			0x01
+#define AIC31XX_HSD_HS			0x03
+
 /* AIC31XX_MICBIAS */
 #define AIC31XX_MICBIAS_MASK		GENMASK(1, 0)
 #define AIC31XX_MICBIAS_SHIFT		0
-- 
2.15.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v2 17/19] ASoC: tlv320aic31xx: Add overflow detection support
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel, devicetree, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

Similar to short circuit detection, when the ADC/DAC is saturated and
overflows poor audio quality can result and should be reported to the
user. This device support Automatic Dynamic Range Compression (DRC)
to reduce this but it is not enabled currently in this driver.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 20 +++++++++++++++++++-
 sound/soc/codecs/tlv320aic31xx.h |  7 +++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index fd3109366377..094b1596f9cc 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1277,6 +1277,23 @@ static irqreturn_t aic31xx_irq(int irq, void *data)
 	if (value & AIC31XX_HPRSCDETECT)
 		dev_err(dev, "Short circuit on Right output is detected\n");
 
+	ret = regmap_read(aic31xx->regmap, AIC31XX_OFFLAG, &value);
+	if (ret) {
+		dev_err(dev, "Failed to read overflow flag: %d\n", ret);
+		return IRQ_NONE;
+	}
+
+	if (value & AIC31XX_DAC_OF_LEFT)
+		dev_err(dev, "Left-channel DAC overflow has occurred\n");
+	if (value & AIC31XX_DAC_OF_RIGHT)
+		dev_err(dev, "Right-channel DAC overflow has occurred\n");
+	if (value & AIC31XX_DAC_OF_SHIFTER)
+		dev_err(dev, "DAC barrel shifter overflow has occurred\n");
+	if (value & AIC31XX_ADC_OF)
+		dev_err(dev, "ADC overflow has occurred\n");
+	if (value & AIC31XX_ADC_OF_SHIFTER)
+		dev_err(dev, "ADC barrel shifter overflow has occurred\n");
+
 	return IRQ_HANDLED;
 }
 
@@ -1348,7 +1365,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 				   AIC31XX_GPIO1_FUNC_SHIFT);
 
 		regmap_write(aic31xx->regmap, AIC31XX_INT1CTRL,
-			     AIC31XX_SC);
+			     AIC31XX_SC |
+			     AIC31XX_ENGINE);
 
 		ret = devm_request_threaded_irq(aic31xx->dev, aic31xx->irq,
 						NULL, aic31xx_irq,
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
index 9dc85b6f6ad3..d062663f66b5 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -166,6 +166,13 @@ enum aic31xx_type {
 #define AIC31XX_HPRDRVPWRSTATUS_MASK	BIT(1)
 #define AIC31XX_SPRDRVPWRSTATUS_MASK	BIT(0)
 
+/* AIC31XX_OFFLAG */
+#define AIC31XX_DAC_OF_LEFT		BIT(7)
+#define AIC31XX_DAC_OF_RIGHT		BIT(6)
+#define AIC31XX_DAC_OF_SHIFTER		BIT(5)
+#define AIC31XX_ADC_OF			BIT(3)
+#define AIC31XX_ADC_OF_SHIFTER		BIT(1)
+
 /* AIC31XX_INTRDACFLAG */
 #define AIC31XX_HPLSCDETECT		BIT(7)
 #define AIC31XX_HPRSCDETECT		BIT(6)
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 16/19] ASoC: tlv320aic31xx: Add short circuit detection support
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel, devicetree, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

These devices support detecting and reporting short circuits across
the output stages. Add support for reporting these issue. Do this
by registering an interrupt if available and enabling this error
to trigger that interrupt in the device.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 42 ++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/tlv320aic31xx.h | 16 +++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 77ae8f36a943..fd3109366377 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -164,6 +164,7 @@ struct aic31xx_priv {
 	unsigned int sysclk;
 	u8 p_div;
 	int rate_div_line;
+	int irq;
 };
 
 struct aic31xx_rate_divs {
@@ -1258,6 +1259,27 @@ static const struct acpi_device_id aic31xx_acpi_match[] = {
 MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match);
 #endif
 
+static irqreturn_t aic31xx_irq(int irq, void *data)
+{
+	struct aic31xx_priv *aic31xx = (struct aic31xx_priv *)data;
+	struct device *dev = aic31xx->dev;
+	unsigned int value;
+	int ret;
+
+	ret = regmap_read(aic31xx->regmap, AIC31XX_INTRDACFLAG, &value);
+	if (ret) {
+		dev_err(dev, "Failed to read interrupt mask: %d\n", ret);
+		return IRQ_NONE;
+	}
+
+	if (value & AIC31XX_HPLSCDETECT)
+		dev_err(dev, "Short circuit on Left output is detected\n");
+	if (value & AIC31XX_HPRSCDETECT)
+		dev_err(dev, "Short circuit on Right output is detected\n");
+
+	return IRQ_HANDLED;
+}
+
 static int aic31xx_i2c_probe(struct i2c_client *i2c,
 			     const struct i2c_device_id *id)
 {
@@ -1280,6 +1302,7 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 		return ret;
 	}
 	aic31xx->dev = &i2c->dev;
+	aic31xx->irq = i2c->irq;
 
 	aic31xx->codec_type = id->driver_data;
 
@@ -1318,6 +1341,25 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 		return ret;
 	}
 
+	if (aic31xx->irq > 0) {
+		regmap_update_bits(aic31xx->regmap, AIC31XX_GPIO1,
+				   AIC31XX_GPIO1_FUNC_MASK,
+				   AIC31XX_GPIO1_INT1 <<
+				   AIC31XX_GPIO1_FUNC_SHIFT);
+
+		regmap_write(aic31xx->regmap, AIC31XX_INT1CTRL,
+			     AIC31XX_SC);
+
+		ret = devm_request_threaded_irq(aic31xx->dev, aic31xx->irq,
+						NULL, aic31xx_irq,
+						IRQF_ONESHOT, "aic31xx-irq",
+						aic31xx);
+		if (ret) {
+			dev_err(aic31xx->dev, "Unable to request IRQ\n");
+			return ret;
+		}
+	}
+
 	if (aic31xx->codec_type & DAC31XX_BIT)
 		return snd_soc_register_codec(&i2c->dev,
 				&soc_codec_driver_aic31xx,
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
index ab94e6a0c742..9dc85b6f6ad3 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -184,6 +184,22 @@ enum aic31xx_type {
 #define AIC31XX_SC			BIT(3)
 #define AIC31XX_ENGINE			BIT(2)
 
+/* AIC31XX_GPIO1 */
+#define AIC31XX_GPIO1_FUNC_MASK		GENMASK(5, 2)
+#define AIC31XX_GPIO1_FUNC_SHIFT	2
+#define AIC31XX_GPIO1_DISABLED		0x00
+#define AIC31XX_GPIO1_INPUT		0x01
+#define AIC31XX_GPIO1_GPI		0x02
+#define AIC31XX_GPIO1_GPO		0x03
+#define AIC31XX_GPIO1_CLKOUT		0x04
+#define AIC31XX_GPIO1_INT1		0x05
+#define AIC31XX_GPIO1_INT2		0x06
+#define AIC31XX_GPIO1_ADC_WCLK		0x07
+#define AIC31XX_GPIO1_SBCLK		0x08
+#define AIC31XX_GPIO1_SWCLK		0x09
+#define AIC31XX_GPIO1_ADC_MOD_CLK	0x10
+#define AIC31XX_GPIO1_SDOUT		0x11
+
 /* AIC31XX_DACSETUP */
 #define AIC31XX_SOFTSTEP_MASK		GENMASK(1, 0)
 
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 15/19] ASoC: tlv320aic31xx: Reset registers during power up
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: devicetree, alsa-devel, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

Add a reset function that toggles the reset line if available or uses
the software reset command otherwise. Use this in power up to ensure the
registers are in a sane state. This is useful when the driver module
is reloaded, or after Kexec, warm-reboots, etc..

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index b51c2777e8d1..77ae8f36a943 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1031,6 +1031,24 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
+static int aic31xx_reset(struct aic31xx_priv *aic31xx)
+{
+	int ret = 0;
+
+	if (aic31xx->gpio_reset) {
+		gpiod_set_value(aic31xx->gpio_reset, 1);
+		ndelay(10); /* At least 10ns */
+		gpiod_set_value(aic31xx->gpio_reset, 0);
+	} else {
+		ret = regmap_write(aic31xx->regmap, AIC31XX_RESET, 1);
+		if (ret < 0)
+			dev_err(aic31xx->dev, "Could not reset device\n");
+	}
+	mdelay(1); /* At least 1ms */
+
+	return ret;
+}
+
 static void aic31xx_clk_on(struct snd_soc_codec *codec)
 {
 	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
@@ -1074,11 +1092,11 @@ static int aic31xx_power_on(struct snd_soc_codec *codec)
 	if (ret)
 		return ret;
 
-	if (aic31xx->gpio_reset) {
-		gpiod_set_value(aic31xx->gpio_reset, 0);
-		udelay(100);
-	}
 	regcache_cache_only(aic31xx->regmap, false);
+
+	/* Reset device registers for a consistent power-on like state */
+	aic31xx_reset(aic31xx);
+
 	ret = regcache_sync(aic31xx->regmap);
 	if (ret) {
 		dev_err(codec->dev,
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 14/19] ASoC: tlv320aic31xx: Remove regulator notification handling
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel, devicetree, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

A regulator being forcefully disabled is a catastrophic event that
should never happen to most devices, especially not sound CODECs.
In addition, our handler sets the reset line but never disables it
as no one is listening for an enable event, this is certainly broken
and was mosy likely just copied from other CODECs, lets just remove
this code.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 50 ----------------------------------------
 1 file changed, 50 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index f7b1ec96d826..b51c2777e8d1 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -161,7 +161,6 @@ struct aic31xx_priv {
 	struct gpio_desc *gpio_reset;
 	int micbias_vg;
 	struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
-	struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
 	unsigned int sysclk;
 	u8 p_div;
 	int rate_div_line;
@@ -1032,28 +1031,6 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
-static int aic31xx_regulator_event(struct notifier_block *nb,
-				   unsigned long event, void *data)
-{
-	struct aic31xx_disable_nb *disable_nb =
-		container_of(nb, struct aic31xx_disable_nb, nb);
-	struct aic31xx_priv *aic31xx = disable_nb->aic31xx;
-
-	if (event & REGULATOR_EVENT_DISABLE) {
-		/*
-		 * Put codec to reset and as at least one of the
-		 * supplies was disabled.
-		 */
-		if (aic31xx->gpio_reset)
-			gpiod_set_value(aic31xx->gpio_reset, 1);
-
-		regcache_mark_dirty(aic31xx->regmap);
-		dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__);
-	}
-
-	return 0;
-}
-
 static void aic31xx_clk_on(struct snd_soc_codec *codec)
 {
 	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
@@ -1167,20 +1144,6 @@ static int aic31xx_codec_probe(struct snd_soc_codec *codec)
 
 	aic31xx->codec = codec;
 
-	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
-		aic31xx->disable_nb[i].nb.notifier_call =
-			aic31xx_regulator_event;
-		aic31xx->disable_nb[i].aic31xx = aic31xx;
-		ret = regulator_register_notifier(aic31xx->supplies[i].consumer,
-						  &aic31xx->disable_nb[i].nb);
-		if (ret) {
-			dev_err(codec->dev,
-				"Failed to request regulator notifier: %d\n",
-				ret);
-			return ret;
-		}
-	}
-
 	regcache_cache_only(aic31xx->regmap, true);
 	regcache_mark_dirty(aic31xx->regmap);
 
@@ -1195,21 +1158,8 @@ static int aic31xx_codec_probe(struct snd_soc_codec *codec)
 	return 0;
 }
 
-static int aic31xx_codec_remove(struct snd_soc_codec *codec)
-{
-	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
-		regulator_unregister_notifier(aic31xx->supplies[i].consumer,
-					      &aic31xx->disable_nb[i].nb);
-
-	return 0;
-}
-
 static const struct snd_soc_codec_driver soc_codec_driver_aic31xx = {
 	.probe			= aic31xx_codec_probe,
-	.remove			= aic31xx_codec_remove,
 	.set_bias_level		= aic31xx_set_bias_level,
 	.suspend_bias_off	= true,
 
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 13/19] ASoC: tlv320aic31xx: Fix inverted BCLK handling
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: devicetree, alsa-devel, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

Currently BCLK inverting is only handled when the DAI format is
DSP, but the BCLK may be inverted in any supported mode. Without
this using this CODEC in any other mode than DSP with the BCLK
inverted leads to bad sampling timing and very poor audio quality.

Fixes: e00447fafbf7 ("ASoC: tlv320aic31xx: Add basic codec driver implementation")

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index b39db3eb06d0..f7b1ec96d826 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -939,6 +939,18 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		return -EINVAL;
 	}
 
+	/* signal polarity */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		iface_reg2 |= AIC31XX_BCLKINV_MASK;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid DAI clock signal polarity\n");
+		return -EINVAL;
+	}
+
 	/* interface format */
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
@@ -946,16 +958,12 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	case SND_SOC_DAIFMT_DSP_A:
 		dsp_a_val = 0x1; /* fall through */
 	case SND_SOC_DAIFMT_DSP_B:
-		/* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */
-		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-		case SND_SOC_DAIFMT_NB_NF:
-			iface_reg2 |= AIC31XX_BCLKINV_MASK;
-			break;
-		case SND_SOC_DAIFMT_IB_NF:
-			break;
-		default:
-			return -EINVAL;
-		}
+		/*
+		 * NOTE: This CODEC samples on the falling edge of BCLK in
+		 * DSP mode, this is inverted compared to what most DAIs
+		 * expect, so we invert for this mode
+		 */
+		iface_reg2 ^= AIC31XX_BCLKINV_MASK;
 		iface_reg1 |= (AIC31XX_DSP_MODE <<
 			       AIC31XX_IFACE1_DATATYPE_SHIFT);
 		break;
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 12/19] ASoC: tlv320aic31xx: Add CODEC clock slave support
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: devicetree, alsa-devel, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

This CODEC supports being the WCLK and/or BCLK slave, add
support for this here.

Also make the alert into an error as alert is more urgent
than needed here and is rarely used.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 41e2d8077a62..b39db3eb06d0 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -926,8 +926,16 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	case SND_SOC_DAIFMT_CBM_CFM:
 		iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER;
 		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+		iface_reg1 |= AIC31XX_WCLK_MASTER;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		iface_reg1 |= AIC31XX_BCLK_MASTER;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
 	default:
-		dev_alert(codec->dev, "Invalid DAI master/slave interface\n");
+		dev_err(codec->dev, "Invalid DAI master/slave interface\n");
 		return -EINVAL;
 	}
 
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 11/19] ASoC: tlv320aic31xx: Check clock and divider before division
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel, devicetree, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

If our set_sysclk DAI callback has not been called yet p_div will be 0
and dividing by this will cause an error. Print an error message and
leave before this.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 252d99af6688..41e2d8077a62 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -755,11 +755,17 @@ static int aic31xx_setup_pll(struct snd_soc_codec *codec,
 {
 	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
 	int bclk_score = snd_soc_params_to_frame_size(params);
-	int mclk_p = aic31xx->sysclk / aic31xx->p_div;
+	int mclk_p;
 	int bclk_n = 0;
 	int match = -1;
 	int i;
 
+	if (!aic31xx->sysclk || !aic31xx->p_div) {
+		dev_err(codec->dev, "Master clock not supplied\n");
+		return -EINVAL;
+	}
+	mclk_p = aic31xx->sysclk / aic31xx->p_div;
+
 	/* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */
 	snd_soc_update_bits(codec, AIC31XX_CLKMUX,
 			    AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL);
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 10/19] ASoC: tlv320aic31xx: Add MICBIAS off setting
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel, devicetree, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

Leaving microphone bias off is a valid setting and even used in the DT
binding document example. Add this setting here and document the same.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/sound/tlv320aic31xx.txt | 1 +
 include/dt-bindings/sound/tlv320aic31xx-micbias.h         | 1 +
 sound/soc/codecs/tlv320aic31xx.c                          | 1 +
 3 files changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
index 5b3c33bb99e5..411cc46a2c58 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
@@ -24,6 +24,7 @@ Optional properties:
 
 - reset-gpios - GPIO specification for the active low RESET input.
 - ai31xx-micbias-vg - MicBias Voltage setting
+        0 or MICBIAS_OFF - MICBIAS output is powered off
         1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V
         2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V
         3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD
diff --git a/include/dt-bindings/sound/tlv320aic31xx-micbias.h b/include/dt-bindings/sound/tlv320aic31xx-micbias.h
index c6895a18a455..069484070fcf 100644
--- a/include/dt-bindings/sound/tlv320aic31xx-micbias.h
+++ b/include/dt-bindings/sound/tlv320aic31xx-micbias.h
@@ -2,6 +2,7 @@
 #ifndef __DT_TLV320AIC31XX_MICBIAS_H
 #define __DT_TLV320AIC31XX_MICBIAS_H
 
+#define MICBIAS_OFF		0
 #define MICBIAS_2_0V		1
 #define MICBIAS_2_5V		2
 #define MICBIAS_AVDDV		3
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 0e00421d363b..252d99af6688 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1298,6 +1298,7 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 	fwnode_property_read_u32(aic31xx->dev->fwnode, "ai31xx-micbias-vg",
 				 &micbias_value);
 	switch (micbias_value) {
+	case MICBIAS_OFF:
 	case MICBIAS_2_0V:
 	case MICBIAS_2_5V:
 	case MICBIAS_AVDDV:
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 09/19] ASoC: tlv320aic31xx: Remove platform data
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: devicetree, alsa-devel, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

Platform data is not used by anyone (at least in upstream) so
drop this data and switch to using fwnode(DT/ACPI) only.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 72 +++++++++++++---------------------------
 sound/soc/codecs/tlv320aic31xx.h |  6 ----
 2 files changed, 23 insertions(+), 55 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index ab03a19f6aaa..0e00421d363b 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -157,8 +157,9 @@ struct aic31xx_priv {
 	u8 i2c_regs_status;
 	struct device *dev;
 	struct regmap *regmap;
+	enum aic31xx_type codec_type;
 	struct gpio_desc *gpio_reset;
-	struct aic31xx_pdata pdata;
+	int micbias_vg;
 	struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
 	struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
 	unsigned int sysclk;
@@ -450,7 +451,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
 		/* change mic bias voltage to user defined */
 		snd_soc_update_bits(codec, AIC31XX_MICBIAS,
 				    AIC31XX_MICBIAS_MASK,
-				    aic31xx->pdata.micbias_vg <<
+				    aic31xx->micbias_vg <<
 				    AIC31XX_MICBIAS_SHIFT);
 		dev_dbg(codec->dev, "%s: turned on\n", __func__);
 		break;
@@ -673,14 +674,14 @@ static int aic31xx_add_controls(struct snd_soc_codec *codec)
 	int ret = 0;
 	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
 
-	if (!(aic31xx->pdata.codec_type & DAC31XX_BIT))
+	if (!(aic31xx->codec_type & DAC31XX_BIT))
 		ret = snd_soc_add_codec_controls(
 			codec, aic31xx_snd_controls,
 			ARRAY_SIZE(aic31xx_snd_controls));
 	if (ret)
 		return ret;
 
-	if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT)
+	if (aic31xx->codec_type & AIC31XX_STEREO_CLASS_D_BIT)
 		ret = snd_soc_add_codec_controls(
 			codec, aic311x_snd_controls,
 			ARRAY_SIZE(aic311x_snd_controls));
@@ -698,7 +699,7 @@ static int aic31xx_add_widgets(struct snd_soc_codec *codec)
 	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
 	int ret = 0;
 
-	if (aic31xx->pdata.codec_type & DAC31XX_BIT) {
+	if (aic31xx->codec_type & DAC31XX_BIT) {
 		ret = snd_soc_dapm_new_controls(
 			dapm, dac31xx_dapm_widgets,
 			ARRAY_SIZE(dac31xx_dapm_widgets));
@@ -722,7 +723,7 @@ static int aic31xx_add_widgets(struct snd_soc_codec *codec)
 			return ret;
 	}
 
-	if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) {
+	if (aic31xx->codec_type & AIC31XX_STEREO_CLASS_D_BIT) {
 		ret = snd_soc_dapm_new_controls(
 			dapm, aic311x_dapm_widgets,
 			ARRAY_SIZE(aic311x_dapm_widgets));
@@ -1257,42 +1258,6 @@ static const struct of_device_id tlv320aic31xx_of_match[] = {
 	{},
 };
 MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match);
-
-static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
-{
-	struct device_node *np = aic31xx->dev->of_node;
-	unsigned int value = MICBIAS_2_0V;
-	int ret;
-
-	of_property_read_u32(np, "ai31xx-micbias-vg", &value);
-	switch (value) {
-	case MICBIAS_2_0V:
-	case MICBIAS_2_5V:
-	case MICBIAS_AVDDV:
-		aic31xx->pdata.micbias_vg = value;
-		break;
-	default:
-		dev_err(aic31xx->dev,
-			"Bad ai31xx-micbias-vg value %d DT\n",
-			value);
-		aic31xx->pdata.micbias_vg = MICBIAS_2_0V;
-	}
-
-	ret = of_get_named_gpio(np, "reset-gpios", 0);
-	if (ret > 0) {
-		aic31xx->pdata.gpio_reset = ret;
-	} else {
-		ret = of_get_named_gpio(np, "gpio-reset", 0);
-		if (ret > 0) {
-			dev_warn(aic31xx->dev, "Using deprecated property \"gpio-reset\", please update your DT");
-			aic31xx->pdata.gpio_reset = ret;
-		}
-	}
-}
-#else /* CONFIG_OF */
-static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
-{
-}
 #endif /* CONFIG_OF */
 
 #ifdef CONFIG_ACPI
@@ -1307,6 +1272,7 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 			     const struct i2c_device_id *id)
 {
 	struct aic31xx_priv *aic31xx;
+	unsigned int micbias_value = MICBIAS_2_0V;
 	int i, ret;
 
 	dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__,
@@ -1325,15 +1291,23 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 	}
 	aic31xx->dev = &i2c->dev;
 
-	aic31xx->pdata.codec_type = id->driver_data;
+	aic31xx->codec_type = id->driver_data;
 
 	dev_set_drvdata(aic31xx->dev, aic31xx);
 
-	if (dev_get_platdata(aic31xx->dev))
-		memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev),
-		       sizeof(aic31xx->pdata));
-	else if (aic31xx->dev->of_node)
-		aic31xx_pdata_from_of(aic31xx);
+	fwnode_property_read_u32(aic31xx->dev->fwnode, "ai31xx-micbias-vg",
+				 &micbias_value);
+	switch (micbias_value) {
+	case MICBIAS_2_0V:
+	case MICBIAS_2_5V:
+	case MICBIAS_AVDDV:
+		aic31xx->micbias_vg = micbias_value;
+		break;
+	default:
+		dev_err(aic31xx->dev, "Bad ai31xx-micbias-vg value %d in DT\n",
+			micbias_value);
+		aic31xx->micbias_vg = MICBIAS_2_0V;
+	}
 
 	aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset",
 						      GPIOD_OUT_LOW);
@@ -1353,7 +1327,7 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 		return ret;
 	}
 
-	if (aic31xx->pdata.codec_type & DAC31XX_BIT)
+	if (aic31xx->codec_type & DAC31XX_BIT)
 		return snd_soc_register_codec(&i2c->dev,
 				&soc_codec_driver_aic31xx,
 				dac31xx_dai_driver,
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
index 15ac7cba86fe..ab94e6a0c742 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -29,12 +29,6 @@ enum aic31xx_type {
 	DAC3101 = DAC31XX_BIT | AIC31XX_STEREO_CLASS_D_BIT,
 };
 
-struct aic31xx_pdata {
-	enum aic31xx_type codec_type;
-	unsigned int gpio_reset;
-	int micbias_vg;
-};
-
 #define AIC31XX_REG(page, reg)	((page * 128) + reg)
 
 #define AIC31XX_PAGECTL		AIC31XX_REG(0, 0) /* Page Control Register */
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 08/19] ASoC: tlv320aic31xx: Switch GPIO handling to use gpiod_* API
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd-l0cyMroinI0@public.gmane.org>

Move to using newer gpiod_* GPIO handling functions. This simplifies
the code and eases dropping platform data in the next patch. Also
remember GPIO are active low, so set "1" to reset.

Signed-off-by: Andrew F. Davis <afd-l0cyMroinI0@public.gmane.org>
---
 sound/soc/codecs/tlv320aic31xx.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index c84febd991a0..ab03a19f6aaa 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -157,6 +157,7 @@ struct aic31xx_priv {
 	u8 i2c_regs_status;
 	struct device *dev;
 	struct regmap *regmap;
+	struct gpio_desc *gpio_reset;
 	struct aic31xx_pdata pdata;
 	struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
 	struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
@@ -1020,8 +1021,8 @@ static int aic31xx_regulator_event(struct notifier_block *nb,
 		 * Put codec to reset and as at least one of the
 		 * supplies was disabled.
 		 */
-		if (gpio_is_valid(aic31xx->pdata.gpio_reset))
-			gpio_set_value(aic31xx->pdata.gpio_reset, 0);
+		if (aic31xx->gpio_reset)
+			gpiod_set_value(aic31xx->gpio_reset, 1);
 
 		regcache_mark_dirty(aic31xx->regmap);
 		dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__);
@@ -1073,8 +1074,8 @@ static int aic31xx_power_on(struct snd_soc_codec *codec)
 	if (ret)
 		return ret;
 
-	if (gpio_is_valid(aic31xx->pdata.gpio_reset)) {
-		gpio_set_value(aic31xx->pdata.gpio_reset, 1);
+	if (aic31xx->gpio_reset) {
+		gpiod_set_value(aic31xx->gpio_reset, 0);
 		udelay(100);
 	}
 	regcache_cache_only(aic31xx->regmap, false);
@@ -1334,15 +1335,11 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
 	else if (aic31xx->dev->of_node)
 		aic31xx_pdata_from_of(aic31xx);
 
-	if (aic31xx->pdata.gpio_reset) {
-		ret = devm_gpio_request_one(aic31xx->dev,
-					    aic31xx->pdata.gpio_reset,
-					    GPIOF_OUT_INIT_HIGH,
-					    "aic31xx-reset-pin");
-		if (ret < 0) {
-			dev_err(aic31xx->dev, "not able to acquire gpio\n");
-			return ret;
-		}
+	aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset",
+						      GPIOD_OUT_LOW);
+	if (IS_ERR(aic31xx->gpio_reset)) {
+		dev_err(aic31xx->dev, "not able to acquire gpio\n");
+		return PTR_ERR(aic31xx->gpio_reset);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
-- 
2.15.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v2 07/19] ASoC: tlv320aic31xx: Merge init function into probe
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: devicetree, alsa-devel, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

The function aic31xx_device_init() is only called from probe and
does nothing that logically shouldn't be in probe, remove this
unneeded function call and move its code into probe where it was called.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 55 ++++++++++++++++------------------------
 1 file changed, 22 insertions(+), 33 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 07c014501e5e..c84febd991a0 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1302,9 +1302,29 @@ static const struct acpi_device_id aic31xx_acpi_match[] = {
 MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match);
 #endif
 
-static int aic31xx_device_init(struct aic31xx_priv *aic31xx)
+static int aic31xx_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
 {
-	int ret, i;
+	struct aic31xx_priv *aic31xx;
+	int i, ret;
+
+	dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__,
+		id->name, (int)id->driver_data);
+
+	aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL);
+	if (!aic31xx)
+		return -ENOMEM;
+
+	aic31xx->regmap = devm_regmap_init_i2c(i2c, &aic31xx_i2c_regmap);
+	if (IS_ERR(aic31xx->regmap)) {
+		ret = PTR_ERR(aic31xx->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+	aic31xx->dev = &i2c->dev;
+
+	aic31xx->pdata.codec_type = id->driver_data;
 
 	dev_set_drvdata(aic31xx->dev, aic31xx);
 
@@ -1336,37 +1356,6 @@ static int aic31xx_device_init(struct aic31xx_priv *aic31xx)
 		return ret;
 	}
 
-	return 0;
-}
-
-static int aic31xx_i2c_probe(struct i2c_client *i2c,
-			     const struct i2c_device_id *id)
-{
-	struct aic31xx_priv *aic31xx;
-	int ret;
-
-	dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__,
-		id->name, (int) id->driver_data);
-
-	aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL);
-	if (!aic31xx)
-		return -ENOMEM;
-
-	aic31xx->regmap = devm_regmap_init_i2c(i2c, &aic31xx_i2c_regmap);
-	if (IS_ERR(aic31xx->regmap)) {
-		ret = PTR_ERR(aic31xx->regmap);
-		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
-			ret);
-		return ret;
-	}
-	aic31xx->dev = &i2c->dev;
-
-	aic31xx->pdata.codec_type = id->driver_data;
-
-	ret = aic31xx_device_init(aic31xx);
-	if (ret)
-		return ret;
-
 	if (aic31xx->pdata.codec_type & DAC31XX_BIT)
 		return snd_soc_register_codec(&i2c->dev,
 				&soc_codec_driver_aic31xx,
-- 
2.15.0

^ permalink raw reply related

* [PATCH v2 06/19] ASoC: tlv320aic31xx: Reformat header file using GENMASK and BIT macros
From: Andrew F. Davis @ 2017-11-29 21:32 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren
  Cc: devicetree, alsa-devel, linux-kernel, Andrew F . Davis
In-Reply-To: <20171129213300.20021-1-afd@ti.com>

We also move the comments describing the registers to after the register
definition to remove non-uniform vertical white-space, this makes
cross-referencing with the datasheet much easier.

Signed-off-by: Andrew F. Davis <afd@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.h | 460 +++++++++++++++++----------------------
 1 file changed, 203 insertions(+), 257 deletions(-)
 rewrite sound/soc/codecs/tlv320aic31xx.h (80%)

diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
dissimilarity index 80%
index 6efea0485392..15ac7cba86fe 100644
--- a/sound/soc/codecs/tlv320aic31xx.h
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -1,257 +1,203 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * ALSA SoC TLV320AIC31xx CODEC Driver Definitions
- *
- * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/
- */
-
-#ifndef _TLV320AIC31XX_H
-#define _TLV320AIC31XX_H
-
-#define AIC31XX_RATES	SNDRV_PCM_RATE_8000_192000
-
-#define AIC31XX_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
-			 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE \
-			 | SNDRV_PCM_FMTBIT_S32_LE)
-
-
-#define AIC31XX_STEREO_CLASS_D_BIT	0x1
-#define AIC31XX_MINIDSP_BIT		0x2
-#define DAC31XX_BIT			0x4
-
-enum aic31xx_type {
-	AIC3100	= 0,
-	AIC3110 = AIC31XX_STEREO_CLASS_D_BIT,
-	AIC3120 = AIC31XX_MINIDSP_BIT,
-	AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT),
-	DAC3100 = DAC31XX_BIT,
-	DAC3101 = DAC31XX_BIT | AIC31XX_STEREO_CLASS_D_BIT,
-};
-
-struct aic31xx_pdata {
-	enum aic31xx_type codec_type;
-	unsigned int gpio_reset;
-	int micbias_vg;
-};
-
-#define AIC31XX_REG(page, reg)	((page * 128) + reg)
-
-/* Page Control Register */
-#define AIC31XX_PAGECTL		AIC31XX_REG(0, 0)
-
-/* Page 0 Registers */
-/* Software reset register */
-#define AIC31XX_RESET		AIC31XX_REG(0, 1)
-/* OT FLAG register */
-#define AIC31XX_OT_FLAG		AIC31XX_REG(0, 3)
-/* Clock clock Gen muxing, Multiplexers*/
-#define AIC31XX_CLKMUX		AIC31XX_REG(0, 4)
-/* PLL P and R-VAL register */
-#define AIC31XX_PLLPR		AIC31XX_REG(0, 5)
-/* PLL J-VAL register */
-#define AIC31XX_PLLJ		AIC31XX_REG(0, 6)
-/* PLL D-VAL MSB register */
-#define AIC31XX_PLLDMSB		AIC31XX_REG(0, 7)
-/* PLL D-VAL LSB register */
-#define AIC31XX_PLLDLSB		AIC31XX_REG(0, 8)
-/* DAC NDAC_VAL register*/
-#define AIC31XX_NDAC		AIC31XX_REG(0, 11)
-/* DAC MDAC_VAL register */
-#define AIC31XX_MDAC		AIC31XX_REG(0, 12)
-/* DAC OSR setting register 1, MSB value */
-#define AIC31XX_DOSRMSB		AIC31XX_REG(0, 13)
-/* DAC OSR setting register 2, LSB value */
-#define AIC31XX_DOSRLSB		AIC31XX_REG(0, 14)
-#define AIC31XX_MINI_DSP_INPOL	AIC31XX_REG(0, 16)
-/* Clock setting register 8, PLL */
-#define AIC31XX_NADC		AIC31XX_REG(0, 18)
-/* Clock setting register 9, PLL */
-#define AIC31XX_MADC		AIC31XX_REG(0, 19)
-/* ADC Oversampling (AOSR) Register */
-#define AIC31XX_AOSR		AIC31XX_REG(0, 20)
-/* Clock setting register 9, Multiplexers */
-#define AIC31XX_CLKOUTMUX	AIC31XX_REG(0, 25)
-/* Clock setting register 10, CLOCKOUT M divider value */
-#define AIC31XX_CLKOUTMVAL	AIC31XX_REG(0, 26)
-/* Audio Interface Setting Register 1 */
-#define AIC31XX_IFACE1		AIC31XX_REG(0, 27)
-/* Audio Data Slot Offset Programming */
-#define AIC31XX_DATA_OFFSET	AIC31XX_REG(0, 28)
-/* Audio Interface Setting Register 2 */
-#define AIC31XX_IFACE2		AIC31XX_REG(0, 29)
-/* Clock setting register 11, BCLK N Divider */
-#define AIC31XX_BCLKN		AIC31XX_REG(0, 30)
-/* Audio Interface Setting Register 3, Secondary Audio Interface */
-#define AIC31XX_IFACESEC1	AIC31XX_REG(0, 31)
-/* Audio Interface Setting Register 4 */
-#define AIC31XX_IFACESEC2	AIC31XX_REG(0, 32)
-/* Audio Interface Setting Register 5 */
-#define AIC31XX_IFACESEC3	AIC31XX_REG(0, 33)
-/* I2C Bus Condition */
-#define AIC31XX_I2C		AIC31XX_REG(0, 34)
-/* ADC FLAG */
-#define AIC31XX_ADCFLAG		AIC31XX_REG(0, 36)
-/* DAC Flag Registers */
-#define AIC31XX_DACFLAG1	AIC31XX_REG(0, 37)
-#define AIC31XX_DACFLAG2	AIC31XX_REG(0, 38)
-/* Sticky Interrupt flag (overflow) */
-#define AIC31XX_OFFLAG		AIC31XX_REG(0, 39)
-/* Sticy DAC Interrupt flags */
-#define AIC31XX_INTRDACFLAG	AIC31XX_REG(0, 44)
-/* Sticy ADC Interrupt flags */
-#define AIC31XX_INTRADCFLAG	AIC31XX_REG(0, 45)
-/* DAC Interrupt flags 2 */
-#define AIC31XX_INTRDACFLAG2	AIC31XX_REG(0, 46)
-/* ADC Interrupt flags 2 */
-#define AIC31XX_INTRADCFLAG2	AIC31XX_REG(0, 47)
-/* INT1 interrupt control */
-#define AIC31XX_INT1CTRL	AIC31XX_REG(0, 48)
-/* INT2 interrupt control */
-#define AIC31XX_INT2CTRL	AIC31XX_REG(0, 49)
-/* GPIO1 control */
-#define AIC31XX_GPIO1		AIC31XX_REG(0, 51)
-
-#define AIC31XX_DACPRB		AIC31XX_REG(0, 60)
-/* ADC Instruction Set Register */
-#define AIC31XX_ADCPRB		AIC31XX_REG(0, 61)
-/* DAC channel setup register */
-#define AIC31XX_DACSETUP	AIC31XX_REG(0, 63)
-/* DAC Mute and volume control register */
-#define AIC31XX_DACMUTE		AIC31XX_REG(0, 64)
-/* Left DAC channel digital volume control */
-#define AIC31XX_LDACVOL		AIC31XX_REG(0, 65)
-/* Right DAC channel digital volume control */
-#define AIC31XX_RDACVOL		AIC31XX_REG(0, 66)
-/* Headset detection */
-#define AIC31XX_HSDETECT	AIC31XX_REG(0, 67)
-/* ADC Digital Mic */
-#define AIC31XX_ADCSETUP	AIC31XX_REG(0, 81)
-/* ADC Digital Volume Control Fine Adjust */
-#define AIC31XX_ADCFGA		AIC31XX_REG(0, 82)
-/* ADC Digital Volume Control Coarse Adjust */
-#define AIC31XX_ADCVOL		AIC31XX_REG(0, 83)
-
-
-/* Page 1 Registers */
-/* Headphone drivers */
-#define AIC31XX_HPDRIVER	AIC31XX_REG(1, 31)
-/* Class-D Speakear Amplifier */
-#define AIC31XX_SPKAMP		AIC31XX_REG(1, 32)
-/* HP Output Drivers POP Removal Settings */
-#define AIC31XX_HPPOP		AIC31XX_REG(1, 33)
-/* Output Driver PGA Ramp-Down Period Control */
-#define AIC31XX_SPPGARAMP	AIC31XX_REG(1, 34)
-/* DAC_L and DAC_R Output Mixer Routing */
-#define AIC31XX_DACMIXERROUTE	AIC31XX_REG(1, 35)
-/* Left Analog Vol to HPL */
-#define AIC31XX_LANALOGHPL	AIC31XX_REG(1, 36)
-/* Right Analog Vol to HPR */
-#define AIC31XX_RANALOGHPR	AIC31XX_REG(1, 37)
-/* Left Analog Vol to SPL */
-#define AIC31XX_LANALOGSPL	AIC31XX_REG(1, 38)
-/* Right Analog Vol to SPR */
-#define AIC31XX_RANALOGSPR	AIC31XX_REG(1, 39)
-/* HPL Driver */
-#define AIC31XX_HPLGAIN		AIC31XX_REG(1, 40)
-/* HPR Driver */
-#define AIC31XX_HPRGAIN		AIC31XX_REG(1, 41)
-/* SPL Driver */
-#define AIC31XX_SPLGAIN		AIC31XX_REG(1, 42)
-/* SPR Driver */
-#define AIC31XX_SPRGAIN		AIC31XX_REG(1, 43)
-/* HP Driver Control */
-#define AIC31XX_HPCONTROL	AIC31XX_REG(1, 44)
-/* MIC Bias Control */
-#define AIC31XX_MICBIAS		AIC31XX_REG(1, 46)
-/* MIC PGA*/
-#define AIC31XX_MICPGA		AIC31XX_REG(1, 47)
-/* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */
-#define AIC31XX_MICPGAPI	AIC31XX_REG(1, 48)
-/* ADC Input Selection for M-Terminal */
-#define AIC31XX_MICPGAMI	AIC31XX_REG(1, 49)
-/* Input CM Settings */
-#define AIC31XX_MICPGACM	AIC31XX_REG(1, 50)
-
-/* Bits, masks and shifts */
-
-/* AIC31XX_CLKMUX */
-#define AIC31XX_PLL_CLKIN_MASK			0x0c
-#define AIC31XX_PLL_CLKIN_SHIFT			2
-#define AIC31XX_PLL_CLKIN_MCLK			0
-#define AIC31XX_CODEC_CLKIN_MASK		0x03
-#define AIC31XX_CODEC_CLKIN_SHIFT		0
-#define AIC31XX_CODEC_CLKIN_PLL			3
-#define AIC31XX_CODEC_CLKIN_BCLK		1
-
-/* AIC31XX_PLLPR, AIC31XX_NDAC, AIC31XX_MDAC, AIC31XX_NADC, AIC31XX_MADC,
-   AIC31XX_BCLKN */
-#define AIC31XX_PLL_MASK		0x7f
-#define AIC31XX_PM_MASK			0x80
-
-/* AIC31XX_IFACE1 */
-#define AIC31XX_WORD_LEN_16BITS		0x00
-#define AIC31XX_WORD_LEN_20BITS		0x01
-#define AIC31XX_WORD_LEN_24BITS		0x02
-#define AIC31XX_WORD_LEN_32BITS		0x03
-#define AIC31XX_IFACE1_DATALEN_MASK	0x30
-#define AIC31XX_IFACE1_DATALEN_SHIFT	(4)
-#define AIC31XX_IFACE1_DATATYPE_MASK	0xC0
-#define AIC31XX_IFACE1_DATATYPE_SHIFT	(6)
-#define AIC31XX_I2S_MODE		0x00
-#define AIC31XX_DSP_MODE		0x01
-#define AIC31XX_RIGHT_JUSTIFIED_MODE	0x02
-#define AIC31XX_LEFT_JUSTIFIED_MODE	0x03
-#define AIC31XX_IFACE1_MASTER_MASK	0x0C
-#define AIC31XX_BCLK_MASTER		0x08
-#define AIC31XX_WCLK_MASTER		0x04
-
-/* AIC31XX_DATA_OFFSET */
-#define AIC31XX_DATA_OFFSET_MASK	0xFF
-
-/* AIC31XX_IFACE2 */
-#define AIC31XX_BCLKINV_MASK		0x08
-#define AIC31XX_BDIVCLK_MASK		0x03
-#define AIC31XX_DAC2BCLK		0x00
-#define AIC31XX_DACMOD2BCLK		0x01
-#define AIC31XX_ADC2BCLK		0x02
-#define AIC31XX_ADCMOD2BCLK		0x03
-
-/* AIC31XX_ADCFLAG */
-#define AIC31XX_ADCPWRSTATUS_MASK		0x40
-
-/* AIC31XX_DACFLAG1 */
-#define AIC31XX_LDACPWRSTATUS_MASK		0x80
-#define AIC31XX_RDACPWRSTATUS_MASK		0x08
-#define AIC31XX_HPLDRVPWRSTATUS_MASK		0x20
-#define AIC31XX_HPRDRVPWRSTATUS_MASK		0x02
-#define AIC31XX_SPLDRVPWRSTATUS_MASK		0x10
-#define AIC31XX_SPRDRVPWRSTATUS_MASK		0x01
-
-/* AIC31XX_INTRDACFLAG */
-#define AIC31XX_HPSCDETECT_MASK			0x80
-#define AIC31XX_BUTTONPRESS_MASK		0x20
-#define AIC31XX_HSPLUG_MASK			0x10
-#define AIC31XX_LDRCTHRES_MASK			0x08
-#define AIC31XX_RDRCTHRES_MASK			0x04
-#define AIC31XX_DACSINT_MASK			0x02
-#define AIC31XX_DACAINT_MASK			0x01
-
-/* AIC31XX_INT1CTRL */
-#define AIC31XX_HSPLUGDET_MASK			0x80
-#define AIC31XX_BUTTONPRESSDET_MASK		0x40
-#define AIC31XX_DRCTHRES_MASK			0x20
-#define AIC31XX_AGCNOISE_MASK			0x10
-#define AIC31XX_OC_MASK				0x08
-#define AIC31XX_ENGINE_MASK			0x04
-
-/* AIC31XX_DACSETUP */
-#define AIC31XX_SOFTSTEP_MASK			0x03
-
-/* AIC31XX_DACMUTE */
-#define AIC31XX_DACMUTE_MASK			0x0C
-
-/* AIC31XX_MICBIAS */
-#define AIC31XX_MICBIAS_MASK			0x03
-#define AIC31XX_MICBIAS_SHIFT			0
-
-#endif	/* _TLV320AIC31XX_H */
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ALSA SoC TLV320AIC31xx CODEC Driver Definitions
+ *
+ * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#ifndef _TLV320AIC31XX_H
+#define _TLV320AIC31XX_H
+
+#define AIC31XX_RATES	SNDRV_PCM_RATE_8000_192000
+
+#define AIC31XX_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
+			 SNDRV_PCM_FMTBIT_S20_3LE | \
+			 SNDRV_PCM_FMTBIT_S24_3LE | \
+			 SNDRV_PCM_FMTBIT_S24_LE | \
+			 SNDRV_PCM_FMTBIT_S32_LE)
+
+#define AIC31XX_STEREO_CLASS_D_BIT	BIT(1)
+#define AIC31XX_MINIDSP_BIT		BIT(2)
+#define DAC31XX_BIT			BIT(3)
+
+enum aic31xx_type {
+	AIC3100	= 0,
+	AIC3110 = AIC31XX_STEREO_CLASS_D_BIT,
+	AIC3120 = AIC31XX_MINIDSP_BIT,
+	AIC3111 = AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT,
+	DAC3100 = DAC31XX_BIT,
+	DAC3101 = DAC31XX_BIT | AIC31XX_STEREO_CLASS_D_BIT,
+};
+
+struct aic31xx_pdata {
+	enum aic31xx_type codec_type;
+	unsigned int gpio_reset;
+	int micbias_vg;
+};
+
+#define AIC31XX_REG(page, reg)	((page * 128) + reg)
+
+#define AIC31XX_PAGECTL		AIC31XX_REG(0, 0) /* Page Control Register */
+
+/* Page 0 Registers */
+#define AIC31XX_RESET		AIC31XX_REG(0, 1) /* Software reset register */
+#define AIC31XX_OT_FLAG		AIC31XX_REG(0, 3) /* OT FLAG register */
+#define AIC31XX_CLKMUX		AIC31XX_REG(0, 4) /* Clock clock Gen muxing, Multiplexers*/
+#define AIC31XX_PLLPR		AIC31XX_REG(0, 5) /* PLL P and R-VAL register */
+#define AIC31XX_PLLJ		AIC31XX_REG(0, 6) /* PLL J-VAL register */
+#define AIC31XX_PLLDMSB		AIC31XX_REG(0, 7) /* PLL D-VAL MSB register */
+#define AIC31XX_PLLDLSB		AIC31XX_REG(0, 8) /* PLL D-VAL LSB register */
+#define AIC31XX_NDAC		AIC31XX_REG(0, 11) /* DAC NDAC_VAL register*/
+#define AIC31XX_MDAC		AIC31XX_REG(0, 12) /* DAC MDAC_VAL register */
+#define AIC31XX_DOSRMSB		AIC31XX_REG(0, 13) /* DAC OSR setting register 1, MSB value */
+#define AIC31XX_DOSRLSB		AIC31XX_REG(0, 14) /* DAC OSR setting register 2, LSB value */
+#define AIC31XX_MINI_DSP_INPOL	AIC31XX_REG(0, 16)
+#define AIC31XX_NADC		AIC31XX_REG(0, 18) /* Clock setting register 8, PLL */
+#define AIC31XX_MADC		AIC31XX_REG(0, 19) /* Clock setting register 9, PLL */
+#define AIC31XX_AOSR		AIC31XX_REG(0, 20) /* ADC Oversampling (AOSR) Register */
+#define AIC31XX_CLKOUTMUX	AIC31XX_REG(0, 25) /* Clock setting register 9, Multiplexers */
+#define AIC31XX_CLKOUTMVAL	AIC31XX_REG(0, 26) /* Clock setting register 10, CLOCKOUT M divider value */
+#define AIC31XX_IFACE1		AIC31XX_REG(0, 27) /* Audio Interface Setting Register 1 */
+#define AIC31XX_DATA_OFFSET	AIC31XX_REG(0, 28) /* Audio Data Slot Offset Programming */
+#define AIC31XX_IFACE2		AIC31XX_REG(0, 29) /* Audio Interface Setting Register 2 */
+#define AIC31XX_BCLKN		AIC31XX_REG(0, 30) /* Clock setting register 11, BCLK N Divider */
+#define AIC31XX_IFACESEC1	AIC31XX_REG(0, 31) /* Audio Interface Setting Register 3, Secondary Audio Interface */
+#define AIC31XX_IFACESEC2	AIC31XX_REG(0, 32) /* Audio Interface Setting Register 4 */
+#define AIC31XX_IFACESEC3	AIC31XX_REG(0, 33) /* Audio Interface Setting Register 5 */
+#define AIC31XX_I2C		AIC31XX_REG(0, 34) /* I2C Bus Condition */
+#define AIC31XX_ADCFLAG		AIC31XX_REG(0, 36) /* ADC FLAG */
+#define AIC31XX_DACFLAG1	AIC31XX_REG(0, 37) /* DAC Flag Registers */
+#define AIC31XX_DACFLAG2	AIC31XX_REG(0, 38)
+#define AIC31XX_OFFLAG		AIC31XX_REG(0, 39) /* Sticky Interrupt flag (overflow) */
+#define AIC31XX_INTRDACFLAG	AIC31XX_REG(0, 44) /* Sticy DAC Interrupt flags */
+#define AIC31XX_INTRADCFLAG	AIC31XX_REG(0, 45) /* Sticy ADC Interrupt flags */
+#define AIC31XX_INTRDACFLAG2	AIC31XX_REG(0, 46) /* DAC Interrupt flags 2 */
+#define AIC31XX_INTRADCFLAG2	AIC31XX_REG(0, 47) /* ADC Interrupt flags 2 */
+#define AIC31XX_INT1CTRL	AIC31XX_REG(0, 48) /* INT1 interrupt control */
+#define AIC31XX_INT2CTRL	AIC31XX_REG(0, 49) /* INT2 interrupt control */
+#define AIC31XX_GPIO1		AIC31XX_REG(0, 51) /* GPIO1 control */
+#define AIC31XX_DACPRB		AIC31XX_REG(0, 60)
+#define AIC31XX_ADCPRB		AIC31XX_REG(0, 61) /* ADC Instruction Set Register */
+#define AIC31XX_DACSETUP	AIC31XX_REG(0, 63) /* DAC channel setup register */
+#define AIC31XX_DACMUTE		AIC31XX_REG(0, 64) /* DAC Mute and volume control register */
+#define AIC31XX_LDACVOL		AIC31XX_REG(0, 65) /* Left DAC channel digital volume control */
+#define AIC31XX_RDACVOL		AIC31XX_REG(0, 66) /* Right DAC channel digital volume control */
+#define AIC31XX_HSDETECT	AIC31XX_REG(0, 67) /* Headset detection */
+#define AIC31XX_ADCSETUP	AIC31XX_REG(0, 81) /* ADC Digital Mic */
+#define AIC31XX_ADCFGA		AIC31XX_REG(0, 82) /* ADC Digital Volume Control Fine Adjust */
+#define AIC31XX_ADCVOL		AIC31XX_REG(0, 83) /* ADC Digital Volume Control Coarse Adjust */
+
+/* Page 1 Registers */
+#define AIC31XX_HPDRIVER	AIC31XX_REG(1, 31) /* Headphone drivers */
+#define AIC31XX_SPKAMP		AIC31XX_REG(1, 32) /* Class-D Speakear Amplifier */
+#define AIC31XX_HPPOP		AIC31XX_REG(1, 33) /* HP Output Drivers POP Removal Settings */
+#define AIC31XX_SPPGARAMP	AIC31XX_REG(1, 34) /* Output Driver PGA Ramp-Down Period Control */
+#define AIC31XX_DACMIXERROUTE	AIC31XX_REG(1, 35) /* DAC_L and DAC_R Output Mixer Routing */
+#define AIC31XX_LANALOGHPL	AIC31XX_REG(1, 36) /* Left Analog Vol to HPL */
+#define AIC31XX_RANALOGHPR	AIC31XX_REG(1, 37) /* Right Analog Vol to HPR */
+#define AIC31XX_LANALOGSPL	AIC31XX_REG(1, 38) /* Left Analog Vol to SPL */
+#define AIC31XX_RANALOGSPR	AIC31XX_REG(1, 39) /* Right Analog Vol to SPR */
+#define AIC31XX_HPLGAIN		AIC31XX_REG(1, 40) /* HPL Driver */
+#define AIC31XX_HPRGAIN		AIC31XX_REG(1, 41) /* HPR Driver */
+#define AIC31XX_SPLGAIN		AIC31XX_REG(1, 42) /* SPL Driver */
+#define AIC31XX_SPRGAIN		AIC31XX_REG(1, 43) /* SPR Driver */
+#define AIC31XX_HPCONTROL	AIC31XX_REG(1, 44) /* HP Driver Control */
+#define AIC31XX_MICBIAS		AIC31XX_REG(1, 46) /* MIC Bias Control */
+#define AIC31XX_MICPGA		AIC31XX_REG(1, 47) /* MIC PGA*/
+#define AIC31XX_MICPGAPI	AIC31XX_REG(1, 48) /* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */
+#define AIC31XX_MICPGAMI	AIC31XX_REG(1, 49) /* ADC Input Selection for M-Terminal */
+#define AIC31XX_MICPGACM	AIC31XX_REG(1, 50) /* Input CM Settings */
+
+/* Bits, masks, and shifts */
+
+/* AIC31XX_CLKMUX */
+#define AIC31XX_PLL_CLKIN_MASK		GENMASK(3, 2)
+#define AIC31XX_PLL_CLKIN_SHIFT		(2)
+#define AIC31XX_PLL_CLKIN_MCLK		0x00
+#define AIC31XX_PLL_CLKIN_BCKL		0x01
+#define AIC31XX_PLL_CLKIN_GPIO1		0x02
+#define AIC31XX_PLL_CLKIN_DIN		0x03
+#define AIC31XX_CODEC_CLKIN_MASK	GENMASK(1, 0)
+#define AIC31XX_CODEC_CLKIN_SHIFT	(0)
+#define AIC31XX_CODEC_CLKIN_MCLK	0x00
+#define AIC31XX_CODEC_CLKIN_BCLK	0x01
+#define AIC31XX_CODEC_CLKIN_GPIO1	0x02
+#define AIC31XX_CODEC_CLKIN_PLL		0x03
+
+/* AIC31XX_PLLPR */
+/* AIC31XX_NDAC */
+/* AIC31XX_MDAC */
+/* AIC31XX_NADC */
+/* AIC31XX_MADC */
+/* AIC31XX_BCLKN */
+#define AIC31XX_PLL_MASK		GENMASK(6, 0)
+#define AIC31XX_PM_MASK			BIT(7)
+
+/* AIC31XX_IFACE1 */
+#define AIC31XX_IFACE1_DATATYPE_MASK	GENMASK(7, 6)
+#define AIC31XX_IFACE1_DATATYPE_SHIFT	(6)
+#define AIC31XX_I2S_MODE		0x00
+#define AIC31XX_DSP_MODE		0x01
+#define AIC31XX_RIGHT_JUSTIFIED_MODE	0x02
+#define AIC31XX_LEFT_JUSTIFIED_MODE	0x03
+#define AIC31XX_IFACE1_DATALEN_MASK	GENMASK(5, 4)
+#define AIC31XX_IFACE1_DATALEN_SHIFT	(4)
+#define AIC31XX_WORD_LEN_16BITS		0x00
+#define AIC31XX_WORD_LEN_20BITS		0x01
+#define AIC31XX_WORD_LEN_24BITS		0x02
+#define AIC31XX_WORD_LEN_32BITS		0x03
+#define AIC31XX_IFACE1_MASTER_MASK	GENMASK(3, 2)
+#define AIC31XX_BCLK_MASTER		BIT(2)
+#define AIC31XX_WCLK_MASTER		BIT(3)
+
+/* AIC31XX_DATA_OFFSET */
+#define AIC31XX_DATA_OFFSET_MASK	GENMASK(7, 0)
+
+/* AIC31XX_IFACE2 */
+#define AIC31XX_BCLKINV_MASK		BIT(3)
+#define AIC31XX_BDIVCLK_MASK		GENMASK(1, 0)
+#define AIC31XX_DAC2BCLK		0x00
+#define AIC31XX_DACMOD2BCLK		0x01
+#define AIC31XX_ADC2BCLK		0x02
+#define AIC31XX_ADCMOD2BCLK		0x03
+
+/* AIC31XX_ADCFLAG */
+#define AIC31XX_ADCPWRSTATUS_MASK	BIT(6)
+
+/* AIC31XX_DACFLAG1 */
+#define AIC31XX_LDACPWRSTATUS_MASK	BIT(7)
+#define AIC31XX_HPLDRVPWRSTATUS_MASK	BIT(5)
+#define AIC31XX_SPLDRVPWRSTATUS_MASK	BIT(4)
+#define AIC31XX_RDACPWRSTATUS_MASK	BIT(3)
+#define AIC31XX_HPRDRVPWRSTATUS_MASK	BIT(1)
+#define AIC31XX_SPRDRVPWRSTATUS_MASK	BIT(0)
+
+/* AIC31XX_INTRDACFLAG */
+#define AIC31XX_HPLSCDETECT		BIT(7)
+#define AIC31XX_HPRSCDETECT		BIT(6)
+#define AIC31XX_BUTTONPRESS		BIT(5)
+#define AIC31XX_HSPLUG			BIT(4)
+#define AIC31XX_LDRCTHRES		BIT(3)
+#define AIC31XX_RDRCTHRES		BIT(2)
+#define AIC31XX_DACSINT			BIT(1)
+#define AIC31XX_DACAINT			BIT(0)
+
+/* AIC31XX_INT1CTRL */
+#define AIC31XX_HSPLUGDET		BIT(7)
+#define AIC31XX_BUTTONPRESSDET		BIT(6)
+#define AIC31XX_DRCTHRES		BIT(5)
+#define AIC31XX_AGCNOISE		BIT(4)
+#define AIC31XX_SC			BIT(3)
+#define AIC31XX_ENGINE			BIT(2)
+
+/* AIC31XX_DACSETUP */
+#define AIC31XX_SOFTSTEP_MASK		GENMASK(1, 0)
+
+/* AIC31XX_DACMUTE */
+#define AIC31XX_DACMUTE_MASK		GENMASK(3, 2)
+
+/* AIC31XX_MICBIAS */
+#define AIC31XX_MICBIAS_MASK		GENMASK(1, 0)
+#define AIC31XX_MICBIAS_SHIFT		0
+
+#endif	/* _TLV320AIC31XX_H */
-- 
2.15.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox