1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * R7S72100 processor support 4 * 5 * Copyright (C) 2019 Marek Vasut <marek.vasut@gmail.com> 6 */ 7 8#include <dm.h> 9#include <asm/global_data.h> 10#include <dm/lists.h> 11#include <dm/pinctrl.h> 12#include <linux/bitops.h> 13#include <linux/io.h> 14#include <linux/err.h> 15 16#define P(bank) (0x0000 + (bank) * 4) 17#define PSR(bank) (0x0100 + (bank) * 4) 18#define PPR(bank) (0x0200 + (bank) * 4) 19#define PM(bank) (0x0300 + (bank) * 4) 20#define PMC(bank) (0x0400 + (bank) * 4) 21#define PFC(bank) (0x0500 + (bank) * 4) 22#define PFCE(bank) (0x0600 + (bank) * 4) 23#define PNOT(bank) (0x0700 + (bank) * 4) 24#define PMSR(bank) (0x0800 + (bank) * 4) 25#define PMCSR(bank) (0x0900 + (bank) * 4) 26#define PFCAE(bank) (0x0A00 + (bank) * 4) 27#define PIBC(bank) (0x4000 + (bank) * 4) 28#define PBDC(bank) (0x4100 + (bank) * 4) 29#define PIPC(bank) (0x4200 + (bank) * 4) 30 31#define RZA1_PINS_PER_PORT 16 32 33DECLARE_GLOBAL_DATA_PTR; 34 35struct r7s72100_pfc_plat { 36 void __iomem *base; 37}; 38 39static void r7s72100_pfc_set_function(struct udevice *dev, u16 bank, u16 line, 40 u16 func, u16 inbuf, u16 bidir) 41{ 42 struct r7s72100_pfc_plat *plat = dev_get_plat(dev); 43 44 clrsetbits_le16(plat->base + PFCAE(bank), BIT(line), 45 (func & BIT(2)) ? BIT(line) : 0); 46 clrsetbits_le16(plat->base + PFCE(bank), BIT(line), 47 (func & BIT(1)) ? BIT(line) : 0); 48 clrsetbits_le16(plat->base + PFC(bank), BIT(line), 49 (func & BIT(0)) ? BIT(line) : 0); 50 51 clrsetbits_le16(plat->base + PIBC(bank), BIT(line), 52 inbuf ? BIT(line) : 0); 53 clrsetbits_le16(plat->base + PBDC(bank), BIT(line), 54 bidir ? BIT(line) : 0); 55 56 setbits_le32(plat->base + PMCSR(bank), BIT(line + 16) | BIT(line)); 57 58 setbits_le16(plat->base + PIPC(bank), BIT(line)); 59} 60 61static int r7s72100_pfc_set_state(struct udevice *dev, struct udevice *config) 62{ 63 const void *blob = gd->fdt_blob; 64 int node = dev_of_offset(config); 65 u32 cells[32]; 66 u16 bank, line, func; 67 int i, count, bidir; 68 69 count = fdtdec_get_int_array_count(blob, node, "pinmux", 70 cells, ARRAY_SIZE(cells)); 71 if (count < 0) { 72 printf("%s: bad pinmux array %d\n", __func__, count); 73 return -EINVAL; 74 } 75 76 if (count > ARRAY_SIZE(cells)) { 77 printf("%s: unsupported pinmux array count %d\n", 78 __func__, count); 79 return -EINVAL; 80 } 81 82 for (i = 0 ; i < count; i++) { 83 func = (cells[i] >> 16) & 0xf; 84 if (func == 0 || func > 8) { 85 printf("Invalid cell %i in node %s!\n", 86 count, ofnode_get_name(dev_ofnode(config))); 87 continue; 88 } 89 90 func = (func - 1) & 0x7; 91 92 bank = (cells[i] / RZA1_PINS_PER_PORT) & 0xff; 93 line = cells[i] % RZA1_PINS_PER_PORT; 94 95 bidir = 0; 96 if (bank == 3 && line == 3 && func == 1) 97 bidir = 1; 98 99 r7s72100_pfc_set_function(dev, bank, line, func, 0, bidir); 100 } 101 102 return 0; 103} 104 105const struct pinctrl_ops r7s72100_pfc_ops = { 106 .set_state = r7s72100_pfc_set_state, 107}; 108 109static int r7s72100_pfc_probe(struct udevice *dev) 110{ 111 struct r7s72100_pfc_plat *plat = dev_get_plat(dev); 112 fdt_addr_t addr_base; 113 ofnode node; 114 115 addr_base = dev_read_addr(dev); 116 if (addr_base == FDT_ADDR_T_NONE) 117 return -EINVAL; 118 119 plat->base = (void __iomem *)addr_base; 120 121 dev_for_each_subnode(node, dev) { 122 struct udevice *cdev; 123 124 if (!ofnode_read_bool(node, "gpio-controller")) 125 continue; 126 127 device_bind_driver_to_node(dev, "r7s72100-gpio", 128 ofnode_get_name(node), 129 node, &cdev); 130 } 131 132 return 0; 133} 134 135static const struct udevice_id r7s72100_pfc_match[] = { 136 { .compatible = "renesas,r7s72100-ports" }, 137 {} 138}; 139 140U_BOOT_DRIVER(r7s72100_pfc) = { 141 .name = "r7s72100_pfc", 142 .id = UCLASS_PINCTRL, 143 .of_match = r7s72100_pfc_match, 144 .probe = r7s72100_pfc_probe, 145 .plat_auto = sizeof(struct r7s72100_pfc_plat), 146 .ops = &r7s72100_pfc_ops, 147}; 148