Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: mcp251xfd: add gpio functionality

The mcp251xfd devices allow two pins to be configured as gpio. Add this
functionality to driver.

Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Tested-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-6-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Gregor Herburger and committed by
Marc Kleine-Budde
c6106336 d35fa005

+163
+1
drivers/net/can/spi/mcp251xfd/Kconfig
··· 5 5 select CAN_RX_OFFLOAD 6 6 select REGMAP 7 7 select WANT_DEV_COREDUMP 8 + select GPIOLIB 8 9 help 9 10 Driver for the Microchip MCP251XFD SPI FD-CAN controller 10 11 family.
+160
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
··· 1797 1797 return 0; 1798 1798 } 1799 1799 1800 + static const char * const mcp251xfd_gpio_names[] = { "GPIO0", "GPIO1" }; 1801 + 1802 + static int mcp251xfd_gpio_request(struct gpio_chip *chip, unsigned int offset) 1803 + { 1804 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1805 + u32 pin_mask = MCP251XFD_REG_IOCON_PM(offset); 1806 + int ret; 1807 + 1808 + if (priv->rx_int && offset == 1) { 1809 + netdev_err(priv->ndev, "Can't use GPIO 1 with RX-INT!\n"); 1810 + return -EINVAL; 1811 + } 1812 + 1813 + ret = pm_runtime_resume_and_get(priv->ndev->dev.parent); 1814 + if (ret) 1815 + return ret; 1816 + 1817 + return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, pin_mask, pin_mask); 1818 + } 1819 + 1820 + static void mcp251xfd_gpio_free(struct gpio_chip *chip, unsigned int offset) 1821 + { 1822 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1823 + 1824 + pm_runtime_put(priv->ndev->dev.parent); 1825 + } 1826 + 1827 + static int mcp251xfd_gpio_get_direction(struct gpio_chip *chip, 1828 + unsigned int offset) 1829 + { 1830 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1831 + u32 mask = MCP251XFD_REG_IOCON_TRIS(offset); 1832 + u32 val; 1833 + int ret; 1834 + 1835 + ret = regmap_read(priv->map_reg, MCP251XFD_REG_IOCON, &val); 1836 + if (ret) 1837 + return ret; 1838 + 1839 + if (mask & val) 1840 + return GPIO_LINE_DIRECTION_IN; 1841 + 1842 + return GPIO_LINE_DIRECTION_OUT; 1843 + } 1844 + 1845 + static int mcp251xfd_gpio_get(struct gpio_chip *chip, unsigned int offset) 1846 + { 1847 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1848 + u32 mask = MCP251XFD_REG_IOCON_GPIO(offset); 1849 + u32 val; 1850 + int ret; 1851 + 1852 + ret = regmap_read(priv->map_reg, MCP251XFD_REG_IOCON, &val); 1853 + if (ret) 1854 + return ret; 1855 + 1856 + return !!(mask & val); 1857 + } 1858 + 1859 + static int mcp251xfd_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, 1860 + unsigned long *bit) 1861 + { 1862 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1863 + u32 val; 1864 + int ret; 1865 + 1866 + ret = regmap_read(priv->map_reg, MCP251XFD_REG_IOCON, &val); 1867 + if (ret) 1868 + return ret; 1869 + 1870 + *bit = FIELD_GET(MCP251XFD_REG_IOCON_GPIO_MASK, val) & *mask; 1871 + 1872 + return 0; 1873 + } 1874 + 1875 + static int mcp251xfd_gpio_direction_output(struct gpio_chip *chip, 1876 + unsigned int offset, int value) 1877 + { 1878 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1879 + u32 dir_mask = MCP251XFD_REG_IOCON_TRIS(offset); 1880 + u32 val_mask = MCP251XFD_REG_IOCON_LAT(offset); 1881 + u32 val; 1882 + 1883 + if (value) 1884 + val = val_mask; 1885 + else 1886 + val = 0; 1887 + 1888 + return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, 1889 + dir_mask | val_mask, val); 1890 + } 1891 + 1892 + static int mcp251xfd_gpio_direction_input(struct gpio_chip *chip, 1893 + unsigned int offset) 1894 + { 1895 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1896 + u32 dir_mask = MCP251XFD_REG_IOCON_TRIS(offset); 1897 + 1898 + return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, dir_mask, dir_mask); 1899 + } 1900 + 1901 + static int mcp251xfd_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 1902 + { 1903 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1904 + u32 val_mask = MCP251XFD_REG_IOCON_LAT(offset); 1905 + u32 val; 1906 + 1907 + if (value) 1908 + val = val_mask; 1909 + else 1910 + val = 0; 1911 + 1912 + return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, val_mask, val); 1913 + } 1914 + 1915 + static int mcp251xfd_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, 1916 + unsigned long *bits) 1917 + { 1918 + struct mcp251xfd_priv *priv = gpiochip_get_data(chip); 1919 + u32 val; 1920 + 1921 + val = FIELD_PREP(MCP251XFD_REG_IOCON_LAT_MASK, *bits); 1922 + 1923 + return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, 1924 + MCP251XFD_REG_IOCON_LAT_MASK, val); 1925 + } 1926 + 1927 + static int mcp251fdx_gpio_setup(struct mcp251xfd_priv *priv) 1928 + { 1929 + struct gpio_chip *gc = &priv->gc; 1930 + 1931 + if (!device_property_present(&priv->spi->dev, "gpio-controller")) 1932 + return 0; 1933 + 1934 + gc->label = dev_name(&priv->spi->dev); 1935 + gc->parent = &priv->spi->dev; 1936 + gc->owner = THIS_MODULE; 1937 + gc->request = mcp251xfd_gpio_request; 1938 + gc->free = mcp251xfd_gpio_free; 1939 + gc->get_direction = mcp251xfd_gpio_get_direction; 1940 + gc->direction_output = mcp251xfd_gpio_direction_output; 1941 + gc->direction_input = mcp251xfd_gpio_direction_input; 1942 + gc->get = mcp251xfd_gpio_get; 1943 + gc->get_multiple = mcp251xfd_gpio_get_multiple; 1944 + gc->set = mcp251xfd_gpio_set; 1945 + gc->set_multiple = mcp251xfd_gpio_set_multiple; 1946 + gc->base = -1; 1947 + gc->can_sleep = true; 1948 + gc->ngpio = ARRAY_SIZE(mcp251xfd_gpio_names); 1949 + gc->names = mcp251xfd_gpio_names; 1950 + 1951 + return devm_gpiochip_add_data(&priv->spi->dev, gc, priv); 1952 + } 1953 + 1800 1954 static int 1801 1955 mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id, 1802 1956 u32 *effective_speed_hz_slow, ··· 2083 1929 goto out_runtime_disable; 2084 1930 2085 1931 mcp251xfd_ethtool_init(priv); 1932 + 1933 + err = mcp251fdx_gpio_setup(priv); 1934 + if (err) { 1935 + dev_err_probe(&priv->spi->dev, err, "Failed to register gpio-controller.\n"); 1936 + goto out_runtime_disable; 1937 + } 2086 1938 2087 1939 err = register_candev(ndev); 2088 1940 if (err)
+2
drivers/net/can/spi/mcp251xfd/mcp251xfd.h
··· 15 15 #include <linux/can/dev.h> 16 16 #include <linux/can/rx-offload.h> 17 17 #include <linux/gpio/consumer.h> 18 + #include <linux/gpio/driver.h> 18 19 #include <linux/kernel.h> 19 20 #include <linux/netdevice.h> 20 21 #include <linux/regmap.h> ··· 677 676 678 677 struct mcp251xfd_devtype_data devtype_data; 679 678 struct can_berr_counter bec; 679 + struct gpio_chip gc; 680 680 }; 681 681 682 682 #define MCP251XFD_IS(_model) \