123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852 |
- /*
- * Abilis Systems TB10x pin control driver
- *
- * Copyright (C) Abilis Systems 2012
- *
- * Author: Christian Ruppert <christian.ruppert@abilis.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <linux/stringify.h>
- #include <linux/pinctrl/pinctrl.h>
- #include <linux/pinctrl/pinmux.h>
- #include <linux/pinctrl/machine.h>
- #include <linux/platform_device.h>
- #include <linux/module.h>
- #include <linux/mutex.h>
- #include <linux/err.h>
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/slab.h>
- #include "pinctrl-utils.h"
- #define TB10X_PORT1 (0)
- #define TB10X_PORT2 (16)
- #define TB10X_PORT3 (32)
- #define TB10X_PORT4 (48)
- #define TB10X_PORT5 (128)
- #define TB10X_PORT6 (64)
- #define TB10X_PORT7 (80)
- #define TB10X_PORT8 (96)
- #define TB10X_PORT9 (112)
- #define TB10X_GPIOS (256)
- #define PCFG_PORT_BITWIDTH (2)
- #define PCFG_PORT_MASK(PORT) \
- (((1 << PCFG_PORT_BITWIDTH) - 1) << (PCFG_PORT_BITWIDTH * (PORT)))
- static const struct pinctrl_pin_desc tb10x_pins[] = {
- /* Port 1 */
- PINCTRL_PIN(TB10X_PORT1 + 0, "MICLK_S0"),
- PINCTRL_PIN(TB10X_PORT1 + 1, "MISTRT_S0"),
- PINCTRL_PIN(TB10X_PORT1 + 2, "MIVAL_S0"),
- PINCTRL_PIN(TB10X_PORT1 + 3, "MDI_S0"),
- PINCTRL_PIN(TB10X_PORT1 + 4, "GPIOA0"),
- PINCTRL_PIN(TB10X_PORT1 + 5, "GPIOA1"),
- PINCTRL_PIN(TB10X_PORT1 + 6, "GPIOA2"),
- PINCTRL_PIN(TB10X_PORT1 + 7, "MDI_S1"),
- PINCTRL_PIN(TB10X_PORT1 + 8, "MIVAL_S1"),
- PINCTRL_PIN(TB10X_PORT1 + 9, "MISTRT_S1"),
- PINCTRL_PIN(TB10X_PORT1 + 10, "MICLK_S1"),
- /* Port 2 */
- PINCTRL_PIN(TB10X_PORT2 + 0, "MICLK_S2"),
- PINCTRL_PIN(TB10X_PORT2 + 1, "MISTRT_S2"),
- PINCTRL_PIN(TB10X_PORT2 + 2, "MIVAL_S2"),
- PINCTRL_PIN(TB10X_PORT2 + 3, "MDI_S2"),
- PINCTRL_PIN(TB10X_PORT2 + 4, "GPIOC0"),
- PINCTRL_PIN(TB10X_PORT2 + 5, "GPIOC1"),
- PINCTRL_PIN(TB10X_PORT2 + 6, "GPIOC2"),
- PINCTRL_PIN(TB10X_PORT2 + 7, "MDI_S3"),
- PINCTRL_PIN(TB10X_PORT2 + 8, "MIVAL_S3"),
- PINCTRL_PIN(TB10X_PORT2 + 9, "MISTRT_S3"),
- PINCTRL_PIN(TB10X_PORT2 + 10, "MICLK_S3"),
- /* Port 3 */
- PINCTRL_PIN(TB10X_PORT3 + 0, "MICLK_S4"),
- PINCTRL_PIN(TB10X_PORT3 + 1, "MISTRT_S4"),
- PINCTRL_PIN(TB10X_PORT3 + 2, "MIVAL_S4"),
- PINCTRL_PIN(TB10X_PORT3 + 3, "MDI_S4"),
- PINCTRL_PIN(TB10X_PORT3 + 4, "GPIOE0"),
- PINCTRL_PIN(TB10X_PORT3 + 5, "GPIOE1"),
- PINCTRL_PIN(TB10X_PORT3 + 6, "GPIOE2"),
- PINCTRL_PIN(TB10X_PORT3 + 7, "MDI_S5"),
- PINCTRL_PIN(TB10X_PORT3 + 8, "MIVAL_S5"),
- PINCTRL_PIN(TB10X_PORT3 + 9, "MISTRT_S5"),
- PINCTRL_PIN(TB10X_PORT3 + 10, "MICLK_S5"),
- /* Port 4 */
- PINCTRL_PIN(TB10X_PORT4 + 0, "MICLK_S6"),
- PINCTRL_PIN(TB10X_PORT4 + 1, "MISTRT_S6"),
- PINCTRL_PIN(TB10X_PORT4 + 2, "MIVAL_S6"),
- PINCTRL_PIN(TB10X_PORT4 + 3, "MDI_S6"),
- PINCTRL_PIN(TB10X_PORT4 + 4, "GPIOG0"),
- PINCTRL_PIN(TB10X_PORT4 + 5, "GPIOG1"),
- PINCTRL_PIN(TB10X_PORT4 + 6, "GPIOG2"),
- PINCTRL_PIN(TB10X_PORT4 + 7, "MDI_S7"),
- PINCTRL_PIN(TB10X_PORT4 + 8, "MIVAL_S7"),
- PINCTRL_PIN(TB10X_PORT4 + 9, "MISTRT_S7"),
- PINCTRL_PIN(TB10X_PORT4 + 10, "MICLK_S7"),
- /* Port 5 */
- PINCTRL_PIN(TB10X_PORT5 + 0, "PC_CE1N"),
- PINCTRL_PIN(TB10X_PORT5 + 1, "PC_CE2N"),
- PINCTRL_PIN(TB10X_PORT5 + 2, "PC_REGN"),
- PINCTRL_PIN(TB10X_PORT5 + 3, "PC_INPACKN"),
- PINCTRL_PIN(TB10X_PORT5 + 4, "PC_OEN"),
- PINCTRL_PIN(TB10X_PORT5 + 5, "PC_WEN"),
- PINCTRL_PIN(TB10X_PORT5 + 6, "PC_IORDN"),
- PINCTRL_PIN(TB10X_PORT5 + 7, "PC_IOWRN"),
- PINCTRL_PIN(TB10X_PORT5 + 8, "PC_RDYIRQN"),
- PINCTRL_PIN(TB10X_PORT5 + 9, "PC_WAITN"),
- PINCTRL_PIN(TB10X_PORT5 + 10, "PC_A0"),
- PINCTRL_PIN(TB10X_PORT5 + 11, "PC_A1"),
- PINCTRL_PIN(TB10X_PORT5 + 12, "PC_A2"),
- PINCTRL_PIN(TB10X_PORT5 + 13, "PC_A3"),
- PINCTRL_PIN(TB10X_PORT5 + 14, "PC_A4"),
- PINCTRL_PIN(TB10X_PORT5 + 15, "PC_A5"),
- PINCTRL_PIN(TB10X_PORT5 + 16, "PC_A6"),
- PINCTRL_PIN(TB10X_PORT5 + 17, "PC_A7"),
- PINCTRL_PIN(TB10X_PORT5 + 18, "PC_A8"),
- PINCTRL_PIN(TB10X_PORT5 + 19, "PC_A9"),
- PINCTRL_PIN(TB10X_PORT5 + 20, "PC_A10"),
- PINCTRL_PIN(TB10X_PORT5 + 21, "PC_A11"),
- PINCTRL_PIN(TB10X_PORT5 + 22, "PC_A12"),
- PINCTRL_PIN(TB10X_PORT5 + 23, "PC_A13"),
- PINCTRL_PIN(TB10X_PORT5 + 24, "PC_A14"),
- PINCTRL_PIN(TB10X_PORT5 + 25, "PC_D0"),
- PINCTRL_PIN(TB10X_PORT5 + 26, "PC_D1"),
- PINCTRL_PIN(TB10X_PORT5 + 27, "PC_D2"),
- PINCTRL_PIN(TB10X_PORT5 + 28, "PC_D3"),
- PINCTRL_PIN(TB10X_PORT5 + 29, "PC_D4"),
- PINCTRL_PIN(TB10X_PORT5 + 30, "PC_D5"),
- PINCTRL_PIN(TB10X_PORT5 + 31, "PC_D6"),
- PINCTRL_PIN(TB10X_PORT5 + 32, "PC_D7"),
- PINCTRL_PIN(TB10X_PORT5 + 33, "PC_MOSTRT"),
- PINCTRL_PIN(TB10X_PORT5 + 34, "PC_MOVAL"),
- PINCTRL_PIN(TB10X_PORT5 + 35, "PC_MDO0"),
- PINCTRL_PIN(TB10X_PORT5 + 36, "PC_MDO1"),
- PINCTRL_PIN(TB10X_PORT5 + 37, "PC_MDO2"),
- PINCTRL_PIN(TB10X_PORT5 + 38, "PC_MDO3"),
- PINCTRL_PIN(TB10X_PORT5 + 39, "PC_MDO4"),
- PINCTRL_PIN(TB10X_PORT5 + 40, "PC_MDO5"),
- PINCTRL_PIN(TB10X_PORT5 + 41, "PC_MDO6"),
- PINCTRL_PIN(TB10X_PORT5 + 42, "PC_MDO7"),
- PINCTRL_PIN(TB10X_PORT5 + 43, "PC_MISTRT"),
- PINCTRL_PIN(TB10X_PORT5 + 44, "PC_MIVAL"),
- PINCTRL_PIN(TB10X_PORT5 + 45, "PC_MDI0"),
- PINCTRL_PIN(TB10X_PORT5 + 46, "PC_MDI1"),
- PINCTRL_PIN(TB10X_PORT5 + 47, "PC_MDI2"),
- PINCTRL_PIN(TB10X_PORT5 + 48, "PC_MDI3"),
- PINCTRL_PIN(TB10X_PORT5 + 49, "PC_MDI4"),
- PINCTRL_PIN(TB10X_PORT5 + 50, "PC_MDI5"),
- PINCTRL_PIN(TB10X_PORT5 + 51, "PC_MDI6"),
- PINCTRL_PIN(TB10X_PORT5 + 52, "PC_MDI7"),
- PINCTRL_PIN(TB10X_PORT5 + 53, "PC_MICLK"),
- /* Port 6 */
- PINCTRL_PIN(TB10X_PORT6 + 0, "T_MOSTRT_S0"),
- PINCTRL_PIN(TB10X_PORT6 + 1, "T_MOVAL_S0"),
- PINCTRL_PIN(TB10X_PORT6 + 2, "T_MDO_S0"),
- PINCTRL_PIN(TB10X_PORT6 + 3, "T_MOSTRT_S1"),
- PINCTRL_PIN(TB10X_PORT6 + 4, "T_MOVAL_S1"),
- PINCTRL_PIN(TB10X_PORT6 + 5, "T_MDO_S1"),
- PINCTRL_PIN(TB10X_PORT6 + 6, "T_MOSTRT_S2"),
- PINCTRL_PIN(TB10X_PORT6 + 7, "T_MOVAL_S2"),
- PINCTRL_PIN(TB10X_PORT6 + 8, "T_MDO_S2"),
- PINCTRL_PIN(TB10X_PORT6 + 9, "T_MOSTRT_S3"),
- /* Port 7 */
- PINCTRL_PIN(TB10X_PORT7 + 0, "UART0_TXD"),
- PINCTRL_PIN(TB10X_PORT7 + 1, "UART0_RXD"),
- PINCTRL_PIN(TB10X_PORT7 + 2, "UART0_CTS"),
- PINCTRL_PIN(TB10X_PORT7 + 3, "UART0_RTS"),
- PINCTRL_PIN(TB10X_PORT7 + 4, "UART1_TXD"),
- PINCTRL_PIN(TB10X_PORT7 + 5, "UART1_RXD"),
- PINCTRL_PIN(TB10X_PORT7 + 6, "UART1_CTS"),
- PINCTRL_PIN(TB10X_PORT7 + 7, "UART1_RTS"),
- /* Port 8 */
- PINCTRL_PIN(TB10X_PORT8 + 0, "SPI3_CLK"),
- PINCTRL_PIN(TB10X_PORT8 + 1, "SPI3_MISO"),
- PINCTRL_PIN(TB10X_PORT8 + 2, "SPI3_MOSI"),
- PINCTRL_PIN(TB10X_PORT8 + 3, "SPI3_SSN"),
- /* Port 9 */
- PINCTRL_PIN(TB10X_PORT9 + 0, "SPI1_CLK"),
- PINCTRL_PIN(TB10X_PORT9 + 1, "SPI1_MISO"),
- PINCTRL_PIN(TB10X_PORT9 + 2, "SPI1_MOSI"),
- PINCTRL_PIN(TB10X_PORT9 + 3, "SPI1_SSN0"),
- PINCTRL_PIN(TB10X_PORT9 + 4, "SPI1_SSN1"),
- /* Unmuxed GPIOs */
- PINCTRL_PIN(TB10X_GPIOS + 0, "GPIOB0"),
- PINCTRL_PIN(TB10X_GPIOS + 1, "GPIOB1"),
- PINCTRL_PIN(TB10X_GPIOS + 2, "GPIOD0"),
- PINCTRL_PIN(TB10X_GPIOS + 3, "GPIOD1"),
- PINCTRL_PIN(TB10X_GPIOS + 4, "GPIOF0"),
- PINCTRL_PIN(TB10X_GPIOS + 5, "GPIOF1"),
- PINCTRL_PIN(TB10X_GPIOS + 6, "GPIOH0"),
- PINCTRL_PIN(TB10X_GPIOS + 7, "GPIOH1"),
- PINCTRL_PIN(TB10X_GPIOS + 8, "GPIOI0"),
- PINCTRL_PIN(TB10X_GPIOS + 9, "GPIOI1"),
- PINCTRL_PIN(TB10X_GPIOS + 10, "GPIOI2"),
- PINCTRL_PIN(TB10X_GPIOS + 11, "GPIOI3"),
- PINCTRL_PIN(TB10X_GPIOS + 12, "GPIOI4"),
- PINCTRL_PIN(TB10X_GPIOS + 13, "GPIOI5"),
- PINCTRL_PIN(TB10X_GPIOS + 14, "GPIOI6"),
- PINCTRL_PIN(TB10X_GPIOS + 15, "GPIOI7"),
- PINCTRL_PIN(TB10X_GPIOS + 16, "GPIOI8"),
- PINCTRL_PIN(TB10X_GPIOS + 17, "GPIOI9"),
- PINCTRL_PIN(TB10X_GPIOS + 18, "GPIOI10"),
- PINCTRL_PIN(TB10X_GPIOS + 19, "GPIOI11"),
- PINCTRL_PIN(TB10X_GPIOS + 20, "GPION0"),
- PINCTRL_PIN(TB10X_GPIOS + 21, "GPION1"),
- PINCTRL_PIN(TB10X_GPIOS + 22, "GPION2"),
- PINCTRL_PIN(TB10X_GPIOS + 23, "GPION3"),
- #define MAX_PIN (TB10X_GPIOS + 24)
- PINCTRL_PIN(MAX_PIN, "GPION4"),
- };
- /* Port 1 */
- static const unsigned mis0_pins[] = { TB10X_PORT1 + 0, TB10X_PORT1 + 1,
- TB10X_PORT1 + 2, TB10X_PORT1 + 3};
- static const unsigned gpioa_pins[] = { TB10X_PORT1 + 4, TB10X_PORT1 + 5,
- TB10X_PORT1 + 6};
- static const unsigned mis1_pins[] = { TB10X_PORT1 + 7, TB10X_PORT1 + 8,
- TB10X_PORT1 + 9, TB10X_PORT1 + 10};
- static const unsigned mip1_pins[] = { TB10X_PORT1 + 0, TB10X_PORT1 + 1,
- TB10X_PORT1 + 2, TB10X_PORT1 + 3,
- TB10X_PORT1 + 4, TB10X_PORT1 + 5,
- TB10X_PORT1 + 6, TB10X_PORT1 + 7,
- TB10X_PORT1 + 8, TB10X_PORT1 + 9,
- TB10X_PORT1 + 10};
- /* Port 2 */
- static const unsigned mis2_pins[] = { TB10X_PORT2 + 0, TB10X_PORT2 + 1,
- TB10X_PORT2 + 2, TB10X_PORT2 + 3};
- static const unsigned gpioc_pins[] = { TB10X_PORT2 + 4, TB10X_PORT2 + 5,
- TB10X_PORT2 + 6};
- static const unsigned mis3_pins[] = { TB10X_PORT2 + 7, TB10X_PORT2 + 8,
- TB10X_PORT2 + 9, TB10X_PORT2 + 10};
- static const unsigned mip3_pins[] = { TB10X_PORT2 + 0, TB10X_PORT2 + 1,
- TB10X_PORT2 + 2, TB10X_PORT2 + 3,
- TB10X_PORT2 + 4, TB10X_PORT2 + 5,
- TB10X_PORT2 + 6, TB10X_PORT2 + 7,
- TB10X_PORT2 + 8, TB10X_PORT2 + 9,
- TB10X_PORT2 + 10};
- /* Port 3 */
- static const unsigned mis4_pins[] = { TB10X_PORT3 + 0, TB10X_PORT3 + 1,
- TB10X_PORT3 + 2, TB10X_PORT3 + 3};
- static const unsigned gpioe_pins[] = { TB10X_PORT3 + 4, TB10X_PORT3 + 5,
- TB10X_PORT3 + 6};
- static const unsigned mis5_pins[] = { TB10X_PORT3 + 7, TB10X_PORT3 + 8,
- TB10X_PORT3 + 9, TB10X_PORT3 + 10};
- static const unsigned mip5_pins[] = { TB10X_PORT3 + 0, TB10X_PORT3 + 1,
- TB10X_PORT3 + 2, TB10X_PORT3 + 3,
- TB10X_PORT3 + 4, TB10X_PORT3 + 5,
- TB10X_PORT3 + 6, TB10X_PORT3 + 7,
- TB10X_PORT3 + 8, TB10X_PORT3 + 9,
- TB10X_PORT3 + 10};
- /* Port 4 */
- static const unsigned mis6_pins[] = { TB10X_PORT4 + 0, TB10X_PORT4 + 1,
- TB10X_PORT4 + 2, TB10X_PORT4 + 3};
- static const unsigned gpiog_pins[] = { TB10X_PORT4 + 4, TB10X_PORT4 + 5,
- TB10X_PORT4 + 6};
- static const unsigned mis7_pins[] = { TB10X_PORT4 + 7, TB10X_PORT4 + 8,
- TB10X_PORT4 + 9, TB10X_PORT4 + 10};
- static const unsigned mip7_pins[] = { TB10X_PORT4 + 0, TB10X_PORT4 + 1,
- TB10X_PORT4 + 2, TB10X_PORT4 + 3,
- TB10X_PORT4 + 4, TB10X_PORT4 + 5,
- TB10X_PORT4 + 6, TB10X_PORT4 + 7,
- TB10X_PORT4 + 8, TB10X_PORT4 + 9,
- TB10X_PORT4 + 10};
- /* Port 6 */
- static const unsigned mop_pins[] = { TB10X_PORT6 + 0, TB10X_PORT6 + 1,
- TB10X_PORT6 + 2, TB10X_PORT6 + 3,
- TB10X_PORT6 + 4, TB10X_PORT6 + 5,
- TB10X_PORT6 + 6, TB10X_PORT6 + 7,
- TB10X_PORT6 + 8, TB10X_PORT6 + 9};
- static const unsigned mos0_pins[] = { TB10X_PORT6 + 0, TB10X_PORT6 + 1,
- TB10X_PORT6 + 2};
- static const unsigned mos1_pins[] = { TB10X_PORT6 + 3, TB10X_PORT6 + 4,
- TB10X_PORT6 + 5};
- static const unsigned mos2_pins[] = { TB10X_PORT6 + 6, TB10X_PORT6 + 7,
- TB10X_PORT6 + 8};
- static const unsigned mos3_pins[] = { TB10X_PORT6 + 9};
- /* Port 7 */
- static const unsigned uart0_pins[] = { TB10X_PORT7 + 0, TB10X_PORT7 + 1,
- TB10X_PORT7 + 2, TB10X_PORT7 + 3};
- static const unsigned uart1_pins[] = { TB10X_PORT7 + 4, TB10X_PORT7 + 5,
- TB10X_PORT7 + 6, TB10X_PORT7 + 7};
- static const unsigned gpiol_pins[] = { TB10X_PORT7 + 0, TB10X_PORT7 + 1,
- TB10X_PORT7 + 2, TB10X_PORT7 + 3};
- static const unsigned gpiom_pins[] = { TB10X_PORT7 + 4, TB10X_PORT7 + 5,
- TB10X_PORT7 + 6, TB10X_PORT7 + 7};
- /* Port 8 */
- static const unsigned spi3_pins[] = { TB10X_PORT8 + 0, TB10X_PORT8 + 1,
- TB10X_PORT8 + 2, TB10X_PORT8 + 3};
- static const unsigned jtag_pins[] = { TB10X_PORT8 + 0, TB10X_PORT8 + 1,
- TB10X_PORT8 + 2, TB10X_PORT8 + 3};
- /* Port 9 */
- static const unsigned spi1_pins[] = { TB10X_PORT9 + 0, TB10X_PORT9 + 1,
- TB10X_PORT9 + 2, TB10X_PORT9 + 3,
- TB10X_PORT9 + 4};
- static const unsigned gpion_pins[] = { TB10X_PORT9 + 0, TB10X_PORT9 + 1,
- TB10X_PORT9 + 2, TB10X_PORT9 + 3,
- TB10X_PORT9 + 4};
- /* Port 5 */
- static const unsigned gpioj_pins[] = { TB10X_PORT5 + 0, TB10X_PORT5 + 1,
- TB10X_PORT5 + 2, TB10X_PORT5 + 3,
- TB10X_PORT5 + 4, TB10X_PORT5 + 5,
- TB10X_PORT5 + 6, TB10X_PORT5 + 7,
- TB10X_PORT5 + 8, TB10X_PORT5 + 9,
- TB10X_PORT5 + 10, TB10X_PORT5 + 11,
- TB10X_PORT5 + 12, TB10X_PORT5 + 13,
- TB10X_PORT5 + 14, TB10X_PORT5 + 15,
- TB10X_PORT5 + 16, TB10X_PORT5 + 17,
- TB10X_PORT5 + 18, TB10X_PORT5 + 19,
- TB10X_PORT5 + 20, TB10X_PORT5 + 21,
- TB10X_PORT5 + 22, TB10X_PORT5 + 23,
- TB10X_PORT5 + 24, TB10X_PORT5 + 25,
- TB10X_PORT5 + 26, TB10X_PORT5 + 27,
- TB10X_PORT5 + 28, TB10X_PORT5 + 29,
- TB10X_PORT5 + 30, TB10X_PORT5 + 31};
- static const unsigned gpiok_pins[] = { TB10X_PORT5 + 32, TB10X_PORT5 + 33,
- TB10X_PORT5 + 34, TB10X_PORT5 + 35,
- TB10X_PORT5 + 36, TB10X_PORT5 + 37,
- TB10X_PORT5 + 38, TB10X_PORT5 + 39,
- TB10X_PORT5 + 40, TB10X_PORT5 + 41,
- TB10X_PORT5 + 42, TB10X_PORT5 + 43,
- TB10X_PORT5 + 44, TB10X_PORT5 + 45,
- TB10X_PORT5 + 46, TB10X_PORT5 + 47,
- TB10X_PORT5 + 48, TB10X_PORT5 + 49,
- TB10X_PORT5 + 50, TB10X_PORT5 + 51,
- TB10X_PORT5 + 52, TB10X_PORT5 + 53};
- static const unsigned ciplus_pins[] = { TB10X_PORT5 + 0, TB10X_PORT5 + 1,
- TB10X_PORT5 + 2, TB10X_PORT5 + 3,
- TB10X_PORT5 + 4, TB10X_PORT5 + 5,
- TB10X_PORT5 + 6, TB10X_PORT5 + 7,
- TB10X_PORT5 + 8, TB10X_PORT5 + 9,
- TB10X_PORT5 + 10, TB10X_PORT5 + 11,
- TB10X_PORT5 + 12, TB10X_PORT5 + 13,
- TB10X_PORT5 + 14, TB10X_PORT5 + 15,
- TB10X_PORT5 + 16, TB10X_PORT5 + 17,
- TB10X_PORT5 + 18, TB10X_PORT5 + 19,
- TB10X_PORT5 + 20, TB10X_PORT5 + 21,
- TB10X_PORT5 + 22, TB10X_PORT5 + 23,
- TB10X_PORT5 + 24, TB10X_PORT5 + 25,
- TB10X_PORT5 + 26, TB10X_PORT5 + 27,
- TB10X_PORT5 + 28, TB10X_PORT5 + 29,
- TB10X_PORT5 + 30, TB10X_PORT5 + 31,
- TB10X_PORT5 + 32, TB10X_PORT5 + 33,
- TB10X_PORT5 + 34, TB10X_PORT5 + 35,
- TB10X_PORT5 + 36, TB10X_PORT5 + 37,
- TB10X_PORT5 + 38, TB10X_PORT5 + 39,
- TB10X_PORT5 + 40, TB10X_PORT5 + 41,
- TB10X_PORT5 + 42, TB10X_PORT5 + 43,
- TB10X_PORT5 + 44, TB10X_PORT5 + 45,
- TB10X_PORT5 + 46, TB10X_PORT5 + 47,
- TB10X_PORT5 + 48, TB10X_PORT5 + 49,
- TB10X_PORT5 + 50, TB10X_PORT5 + 51,
- TB10X_PORT5 + 52, TB10X_PORT5 + 53};
- static const unsigned mcard_pins[] = { TB10X_PORT5 + 3, TB10X_PORT5 + 10,
- TB10X_PORT5 + 11, TB10X_PORT5 + 12,
- TB10X_PORT5 + 22, TB10X_PORT5 + 23,
- TB10X_PORT5 + 33, TB10X_PORT5 + 35,
- TB10X_PORT5 + 36, TB10X_PORT5 + 37,
- TB10X_PORT5 + 38, TB10X_PORT5 + 39,
- TB10X_PORT5 + 40, TB10X_PORT5 + 41,
- TB10X_PORT5 + 42, TB10X_PORT5 + 43,
- TB10X_PORT5 + 45, TB10X_PORT5 + 46,
- TB10X_PORT5 + 47, TB10X_PORT5 + 48,
- TB10X_PORT5 + 49, TB10X_PORT5 + 50,
- TB10X_PORT5 + 51, TB10X_PORT5 + 52,
- TB10X_PORT5 + 53};
- static const unsigned stc0_pins[] = { TB10X_PORT5 + 34, TB10X_PORT5 + 35,
- TB10X_PORT5 + 36, TB10X_PORT5 + 37,
- TB10X_PORT5 + 38, TB10X_PORT5 + 39,
- TB10X_PORT5 + 40};
- static const unsigned stc1_pins[] = { TB10X_PORT5 + 25, TB10X_PORT5 + 26,
- TB10X_PORT5 + 27, TB10X_PORT5 + 28,
- TB10X_PORT5 + 29, TB10X_PORT5 + 30,
- TB10X_PORT5 + 44};
- /* Unmuxed GPIOs */
- static const unsigned gpiob_pins[] = { TB10X_GPIOS + 0, TB10X_GPIOS + 1};
- static const unsigned gpiod_pins[] = { TB10X_GPIOS + 2, TB10X_GPIOS + 3};
- static const unsigned gpiof_pins[] = { TB10X_GPIOS + 4, TB10X_GPIOS + 5};
- static const unsigned gpioh_pins[] = { TB10X_GPIOS + 6, TB10X_GPIOS + 7};
- static const unsigned gpioi_pins[] = { TB10X_GPIOS + 8, TB10X_GPIOS + 9,
- TB10X_GPIOS + 10, TB10X_GPIOS + 11,
- TB10X_GPIOS + 12, TB10X_GPIOS + 13,
- TB10X_GPIOS + 14, TB10X_GPIOS + 15,
- TB10X_GPIOS + 16, TB10X_GPIOS + 17,
- TB10X_GPIOS + 18, TB10X_GPIOS + 19};
- struct tb10x_pinfuncgrp {
- const char *name;
- const unsigned int *pins;
- const unsigned int pincnt;
- const int port;
- const unsigned int mode;
- const int isgpio;
- };
- #define DEFPINFUNCGRP(NAME, PORT, MODE, ISGPIO) { \
- .name = __stringify(NAME), \
- .pins = NAME##_pins, .pincnt = ARRAY_SIZE(NAME##_pins), \
- .port = (PORT), .mode = (MODE), \
- .isgpio = (ISGPIO), \
- }
- static const struct tb10x_pinfuncgrp tb10x_pingroups[] = {
- DEFPINFUNCGRP(mis0, 0, 0, 0),
- DEFPINFUNCGRP(gpioa, 0, 0, 1),
- DEFPINFUNCGRP(mis1, 0, 0, 0),
- DEFPINFUNCGRP(mip1, 0, 1, 0),
- DEFPINFUNCGRP(mis2, 1, 0, 0),
- DEFPINFUNCGRP(gpioc, 1, 0, 1),
- DEFPINFUNCGRP(mis3, 1, 0, 0),
- DEFPINFUNCGRP(mip3, 1, 1, 0),
- DEFPINFUNCGRP(mis4, 2, 0, 0),
- DEFPINFUNCGRP(gpioe, 2, 0, 1),
- DEFPINFUNCGRP(mis5, 2, 0, 0),
- DEFPINFUNCGRP(mip5, 2, 1, 0),
- DEFPINFUNCGRP(mis6, 3, 0, 0),
- DEFPINFUNCGRP(gpiog, 3, 0, 1),
- DEFPINFUNCGRP(mis7, 3, 0, 0),
- DEFPINFUNCGRP(mip7, 3, 1, 0),
- DEFPINFUNCGRP(gpioj, 4, 0, 1),
- DEFPINFUNCGRP(gpiok, 4, 0, 1),
- DEFPINFUNCGRP(ciplus, 4, 1, 0),
- DEFPINFUNCGRP(mcard, 4, 2, 0),
- DEFPINFUNCGRP(stc0, 4, 3, 0),
- DEFPINFUNCGRP(stc1, 4, 3, 0),
- DEFPINFUNCGRP(mop, 5, 0, 0),
- DEFPINFUNCGRP(mos0, 5, 1, 0),
- DEFPINFUNCGRP(mos1, 5, 1, 0),
- DEFPINFUNCGRP(mos2, 5, 1, 0),
- DEFPINFUNCGRP(mos3, 5, 1, 0),
- DEFPINFUNCGRP(uart0, 6, 0, 0),
- DEFPINFUNCGRP(uart1, 6, 0, 0),
- DEFPINFUNCGRP(gpiol, 6, 1, 1),
- DEFPINFUNCGRP(gpiom, 6, 1, 1),
- DEFPINFUNCGRP(spi3, 7, 0, 0),
- DEFPINFUNCGRP(jtag, 7, 1, 0),
- DEFPINFUNCGRP(spi1, 8, 0, 0),
- DEFPINFUNCGRP(gpion, 8, 1, 1),
- DEFPINFUNCGRP(gpiob, -1, 0, 1),
- DEFPINFUNCGRP(gpiod, -1, 0, 1),
- DEFPINFUNCGRP(gpiof, -1, 0, 1),
- DEFPINFUNCGRP(gpioh, -1, 0, 1),
- DEFPINFUNCGRP(gpioi, -1, 0, 1),
- };
- #undef DEFPINFUNCGRP
- struct tb10x_of_pinfunc {
- const char *name;
- const char *group;
- };
- #define TB10X_PORTS (9)
- /**
- * struct tb10x_port - state of an I/O port
- * @mode: Node this port is currently in.
- * @count: Number of enabled functions which require this port to be
- * configured in @mode.
- */
- struct tb10x_port {
- unsigned int mode;
- unsigned int count;
- };
- /**
- * struct tb10x_pinctrl - TB10x pin controller internal state
- * @pctl: pointer to the pinctrl_dev structure of this pin controller.
- * @base: register set base address.
- * @pingroups: pointer to an array of the pin groups this driver manages.
- * @pinfuncgrpcnt: number of pingroups in @pingroups.
- * @pinfuncs: pointer to an array of pin functions this driver manages.
- * @pinfuncnt: number of pin functions in @pinfuncs.
- * @mutex: mutex for exclusive access to a pin controller's state.
- * @ports: current state of each port.
- * @gpios: Indicates if a given pin is currently used as GPIO (1) or not (0).
- */
- struct tb10x_pinctrl {
- struct pinctrl_dev *pctl;
- void *base;
- const struct tb10x_pinfuncgrp *pingroups;
- unsigned int pinfuncgrpcnt;
- struct tb10x_of_pinfunc *pinfuncs;
- unsigned int pinfuncnt;
- struct mutex mutex;
- struct tb10x_port ports[TB10X_PORTS];
- DECLARE_BITMAP(gpios, MAX_PIN + 1);
- };
- static inline void tb10x_pinctrl_set_config(struct tb10x_pinctrl *state,
- unsigned int port, unsigned int mode)
- {
- u32 pcfg;
- if (state->ports[port].count)
- return;
- state->ports[port].mode = mode;
- pcfg = ioread32(state->base) & ~(PCFG_PORT_MASK(port));
- pcfg |= (mode << (PCFG_PORT_BITWIDTH * port)) & PCFG_PORT_MASK(port);
- iowrite32(pcfg, state->base);
- }
- static inline unsigned int tb10x_pinctrl_get_config(
- struct tb10x_pinctrl *state,
- unsigned int port)
- {
- return (ioread32(state->base) & PCFG_PORT_MASK(port))
- >> (PCFG_PORT_BITWIDTH * port);
- }
- static int tb10x_get_groups_count(struct pinctrl_dev *pctl)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- return state->pinfuncgrpcnt;
- }
- static const char *tb10x_get_group_name(struct pinctrl_dev *pctl, unsigned n)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- return state->pingroups[n].name;
- }
- static int tb10x_get_group_pins(struct pinctrl_dev *pctl, unsigned n,
- unsigned const **pins,
- unsigned * const num_pins)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- *pins = state->pingroups[n].pins;
- *num_pins = state->pingroups[n].pincnt;
- return 0;
- }
- static int tb10x_dt_node_to_map(struct pinctrl_dev *pctl,
- struct device_node *np_config,
- struct pinctrl_map **map, unsigned *num_maps)
- {
- const char *string;
- unsigned reserved_maps = 0;
- int ret = 0;
- if (of_property_read_string(np_config, "abilis,function", &string)) {
- pr_err("%pOF: No abilis,function property in device tree.\n",
- np_config);
- return -EINVAL;
- }
- *map = NULL;
- *num_maps = 0;
- ret = pinctrl_utils_reserve_map(pctl, map, &reserved_maps,
- num_maps, 1);
- if (ret)
- goto out;
- ret = pinctrl_utils_add_map_mux(pctl, map, &reserved_maps,
- num_maps, string, np_config->name);
- out:
- return ret;
- }
- static const struct pinctrl_ops tb10x_pinctrl_ops = {
- .get_groups_count = tb10x_get_groups_count,
- .get_group_name = tb10x_get_group_name,
- .get_group_pins = tb10x_get_group_pins,
- .dt_node_to_map = tb10x_dt_node_to_map,
- .dt_free_map = pinctrl_utils_free_map,
- };
- static int tb10x_get_functions_count(struct pinctrl_dev *pctl)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- return state->pinfuncnt;
- }
- static const char *tb10x_get_function_name(struct pinctrl_dev *pctl,
- unsigned n)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- return state->pinfuncs[n].name;
- }
- static int tb10x_get_function_groups(struct pinctrl_dev *pctl,
- unsigned n, const char * const **groups,
- unsigned * const num_groups)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- *groups = &state->pinfuncs[n].group;
- *num_groups = 1;
- return 0;
- }
- static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl,
- struct pinctrl_gpio_range *range,
- unsigned pin)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- int muxport = -1;
- int muxmode = -1;
- int i;
- mutex_lock(&state->mutex);
- /*
- * Figure out to which port the requested GPIO belongs and how to
- * configure that port.
- * This loop also checks for pin conflicts between GPIOs and other
- * functions.
- */
- for (i = 0; i < state->pinfuncgrpcnt; i++) {
- const struct tb10x_pinfuncgrp *pfg = &state->pingroups[i];
- unsigned int mode = pfg->mode;
- int j, port = pfg->port;
- /*
- * Skip pin groups which are always mapped and don't need
- * to be configured.
- */
- if (port < 0)
- continue;
- for (j = 0; j < pfg->pincnt; j++) {
- if (pin == pfg->pins[j]) {
- if (pfg->isgpio) {
- /*
- * Remember the GPIO-only setting of
- * the port this pin belongs to.
- */
- muxport = port;
- muxmode = mode;
- } else if (state->ports[port].count
- && (state->ports[port].mode == mode)) {
- /*
- * Error: The requested pin is already
- * used for something else.
- */
- mutex_unlock(&state->mutex);
- return -EBUSY;
- }
- break;
- }
- }
- }
- /*
- * If we haven't returned an error at this point, the GPIO pin is not
- * used by another function and the GPIO request can be granted:
- * Register pin as being used as GPIO so we don't allocate it to
- * another function later.
- */
- set_bit(pin, state->gpios);
- /*
- * Potential conflicts between GPIOs and pin functions were caught
- * earlier in this function and tb10x_pinctrl_set_config will do the
- * Right Thing, either configure the port in GPIO only mode or leave
- * another mode compatible with this GPIO request untouched.
- */
- if (muxport >= 0)
- tb10x_pinctrl_set_config(state, muxport, muxmode);
- mutex_unlock(&state->mutex);
- return 0;
- }
- static void tb10x_gpio_disable_free(struct pinctrl_dev *pctl,
- struct pinctrl_gpio_range *range,
- unsigned pin)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- mutex_lock(&state->mutex);
- clear_bit(pin, state->gpios);
- mutex_unlock(&state->mutex);
- }
- static int tb10x_pctl_set_mux(struct pinctrl_dev *pctl,
- unsigned func_selector, unsigned group_selector)
- {
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- const struct tb10x_pinfuncgrp *grp = &state->pingroups[group_selector];
- int i;
- if (grp->port < 0)
- return 0;
- mutex_lock(&state->mutex);
- /*
- * Check if the requested function is compatible with previously
- * requested functions.
- */
- if (state->ports[grp->port].count
- && (state->ports[grp->port].mode != grp->mode)) {
- mutex_unlock(&state->mutex);
- return -EBUSY;
- }
- /*
- * Check if the requested function is compatible with previously
- * requested GPIOs.
- */
- for (i = 0; i < grp->pincnt; i++)
- if (test_bit(grp->pins[i], state->gpios)) {
- mutex_unlock(&state->mutex);
- return -EBUSY;
- }
- tb10x_pinctrl_set_config(state, grp->port, grp->mode);
- state->ports[grp->port].count++;
- mutex_unlock(&state->mutex);
- return 0;
- }
- static const struct pinmux_ops tb10x_pinmux_ops = {
- .get_functions_count = tb10x_get_functions_count,
- .get_function_name = tb10x_get_function_name,
- .get_function_groups = tb10x_get_function_groups,
- .gpio_request_enable = tb10x_gpio_request_enable,
- .gpio_disable_free = tb10x_gpio_disable_free,
- .set_mux = tb10x_pctl_set_mux,
- };
- static struct pinctrl_desc tb10x_pindesc = {
- .name = "TB10x",
- .pins = tb10x_pins,
- .npins = ARRAY_SIZE(tb10x_pins),
- .owner = THIS_MODULE,
- .pctlops = &tb10x_pinctrl_ops,
- .pmxops = &tb10x_pinmux_ops,
- };
- static int tb10x_pinctrl_probe(struct platform_device *pdev)
- {
- int ret = -EINVAL;
- struct resource *mem;
- struct device *dev = &pdev->dev;
- struct device_node *of_node = dev->of_node;
- struct device_node *child;
- struct tb10x_pinctrl *state;
- int i;
- if (!of_node) {
- dev_err(dev, "No device tree node found.\n");
- return -EINVAL;
- }
- state = devm_kzalloc(dev, sizeof(struct tb10x_pinctrl) +
- of_get_child_count(of_node)
- * sizeof(struct tb10x_of_pinfunc),
- GFP_KERNEL);
- if (!state)
- return -ENOMEM;
- platform_set_drvdata(pdev, state);
- state->pinfuncs = (struct tb10x_of_pinfunc *)(state + 1);
- mutex_init(&state->mutex);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- state->base = devm_ioremap_resource(dev, mem);
- if (IS_ERR(state->base)) {
- ret = PTR_ERR(state->base);
- goto fail;
- }
- state->pingroups = tb10x_pingroups;
- state->pinfuncgrpcnt = ARRAY_SIZE(tb10x_pingroups);
- for (i = 0; i < TB10X_PORTS; i++)
- state->ports[i].mode = tb10x_pinctrl_get_config(state, i);
- for_each_child_of_node(of_node, child) {
- const char *name;
- if (!of_property_read_string(child, "abilis,function",
- &name)) {
- state->pinfuncs[state->pinfuncnt].name = child->name;
- state->pinfuncs[state->pinfuncnt].group = name;
- state->pinfuncnt++;
- }
- }
- state->pctl = devm_pinctrl_register(dev, &tb10x_pindesc, state);
- if (IS_ERR(state->pctl)) {
- dev_err(dev, "could not register TB10x pin driver\n");
- ret = PTR_ERR(state->pctl);
- goto fail;
- }
- return 0;
- fail:
- mutex_destroy(&state->mutex);
- return ret;
- }
- static int tb10x_pinctrl_remove(struct platform_device *pdev)
- {
- struct tb10x_pinctrl *state = platform_get_drvdata(pdev);
- mutex_destroy(&state->mutex);
- return 0;
- }
- static const struct of_device_id tb10x_pinctrl_dt_ids[] = {
- { .compatible = "abilis,tb10x-iomux" },
- { }
- };
- MODULE_DEVICE_TABLE(of, tb10x_pinctrl_dt_ids);
- static struct platform_driver tb10x_pinctrl_pdrv = {
- .probe = tb10x_pinctrl_probe,
- .remove = tb10x_pinctrl_remove,
- .driver = {
- .name = "tb10x_pinctrl",
- .of_match_table = of_match_ptr(tb10x_pinctrl_dt_ids),
- }
- };
- module_platform_driver(tb10x_pinctrl_pdrv);
- MODULE_AUTHOR("Christian Ruppert <christian.ruppert@abilis.com>");
- MODULE_LICENSE("GPL");
|