/* * SuperH Pin Function Controller Support * * Copyright (c) 2008 Magnus Damm * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ #ifndef __SH_PFC_H #define __SH_PFC_H #include #include #include enum { PINMUX_TYPE_NONE, PINMUX_TYPE_FUNCTION, PINMUX_TYPE_GPIO, PINMUX_TYPE_OUTPUT, PINMUX_TYPE_INPUT, }; #define SH_PFC_PIN_CFG_INPUT (1 << 0) #define SH_PFC_PIN_CFG_OUTPUT (1 << 1) #define SH_PFC_PIN_CFG_PULL_UP (1 << 2) #define SH_PFC_PIN_CFG_PULL_DOWN (1 << 3) #define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4) #define SH_PFC_PIN_CFG_NO_GPIO (1 << 31) struct sh_pfc_pin { u16 pin; u16 enum_id; const char *name; unsigned int configs; }; #define SH_PFC_PIN_GROUP(n) \ { \ .name = #n, \ .pins = n##_pins, \ .mux = n##_mux, \ .nr_pins = ARRAY_SIZE(n##_pins), \ } struct sh_pfc_pin_group { const char *name; const unsigned int *pins; const unsigned int *mux; unsigned int nr_pins; }; /* * Using union vin_data saves memory occupied by the VIN data pins. * VIN_DATA_PIN_GROUP() is a macro used to describe the VIN pin groups * in this case. */ #define VIN_DATA_PIN_GROUP(n, s) \ { \ .name = #n#s, \ .pins = n##_pins.data##s, \ .mux = n##_mux.data##s, \ .nr_pins = ARRAY_SIZE(n##_pins.data##s), \ } union vin_data { unsigned int data24[24]; unsigned int data20[20]; unsigned int data16[16]; unsigned int data12[12]; unsigned int data10[10]; unsigned int data8[8]; unsigned int data4[4]; }; #define SH_PFC_FUNCTION(n) \ { \ .name = #n, \ .groups = n##_groups, \ .nr_groups = ARRAY_SIZE(n##_groups), \ } struct sh_pfc_function { const char *name; const char * const *groups; unsigned int nr_groups; }; struct pinmux_func { u16 enum_id; const char *name; }; struct pinmux_cfg_reg { u32 reg; u8 reg_width, field_width; const u16 *enum_ids; const u8 *var_field_width; }; #define PINMUX_CFG_REG(name, r, r_width, f_width) \ .reg = r, .reg_width = r_width, .field_width = f_width, \ .enum_ids = (const u16 [(r_width / f_width) * (1 << f_width)]) #define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \ .reg = r, .reg_width = r_width, \ .var_field_width = (const u8 [r_width]) \ { var_fw0, var_fwn, 0 }, \ .enum_ids = (const u16 []) struct pinmux_data_reg { u32 reg; u8 reg_width; const u16 *enum_ids; }; #define PINMUX_DATA_REG(name, r, r_width) \ .reg = r, .reg_width = r_width, \ .enum_ids = (const u16 [r_width]) \ struct pinmux_irq { const short *gpios; }; #define PINMUX_IRQ(ids...) \ { .gpios = (const short []) { ids, -1 } } struct pinmux_range { u16 begin; u16 end; u16 force; }; struct sh_pfc; struct sh_pfc_soc_operations { int (*init)(struct sh_pfc *pfc); unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin); void (*set_bias)(struct sh_pfc *pfc, unsigned int pin, unsigned int bias); int (*get_io_voltage)(struct sh_pfc *pfc, unsigned int pin); int (*set_io_voltage)(struct sh_pfc *pfc, unsigned int pin, u16 voltage_mV); }; struct sh_pfc_soc_info { const char *name; const struct sh_pfc_soc_operations *ops; struct pinmux_range input; struct pinmux_range output; struct pinmux_range function; const struct sh_pfc_pin *pins; unsigned int nr_pins; const struct sh_pfc_pin_group *groups; unsigned int nr_groups; const struct sh_pfc_function *functions; unsigned int nr_functions; #ifdef CONFIG_SUPERH const struct pinmux_func *func_gpios; unsigned int nr_func_gpios; #endif const struct pinmux_cfg_reg *cfg_regs; const struct pinmux_data_reg *data_regs; const u16 *pinmux_data; unsigned int pinmux_data_size; const struct pinmux_irq *gpio_irq; unsigned int gpio_irq_size; u32 unlock_reg; }; /* ----------------------------------------------------------------------------- * Helper macros to create pin and port lists */ /* * sh_pfc_soc_info pinmux_data array macros */ #define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0 #define PINMUX_IPSR_NOGP(ispr, fn) \ PINMUX_DATA(fn##_MARK, FN_##fn) #define PINMUX_IPSR_DATA(ipsr, fn) \ PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr) #define PINMUX_IPSR_NOGM(ispr, fn, ms) \ PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms) #define PINMUX_IPSR_NOFN(ipsr, fn, ms) \ PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##ms) #define PINMUX_IPSR_MSEL(ipsr, fn, ms) \ PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn) /* * GP port style (32 ports banks) */ #define PORT_GP_CFG_1(bank, pin, fn, sfx, cfg) fn(bank, pin, GP_##bank##_##pin, sfx, cfg) #define PORT_GP_1(bank, pin, fn, sfx) PORT_GP_CFG_1(bank, pin, fn, sfx, 0) #define PORT_GP_CFG_32(bank, fn, sfx, cfg) \ PORT_GP_CFG_1(bank, 0, fn, sfx, cfg), PORT_GP_CFG_1(bank, 1, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 2, fn, sfx, cfg), PORT_GP_CFG_1(bank, 3, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), PORT_GP_CFG_1(bank, 5, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 6, fn, sfx, cfg), PORT_GP_CFG_1(bank, 7, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 8, fn, sfx, cfg), PORT_GP_CFG_1(bank, 9, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 10, fn, sfx, cfg), PORT_GP_CFG_1(bank, 11, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 12, fn, sfx, cfg), PORT_GP_CFG_1(bank, 13, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 14, fn, sfx, cfg), PORT_GP_CFG_1(bank, 15, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 16, fn, sfx, cfg), PORT_GP_CFG_1(bank, 17, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), PORT_GP_CFG_1(bank, 19, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 20, fn, sfx, cfg), PORT_GP_CFG_1(bank, 21, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 22, fn, sfx, cfg), PORT_GP_CFG_1(bank, 23, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 24, fn, sfx, cfg), PORT_GP_CFG_1(bank, 25, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 26, fn, sfx, cfg), PORT_GP_CFG_1(bank, 27, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 28, fn, sfx, cfg), PORT_GP_CFG_1(bank, 29, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 30, fn, sfx, cfg), PORT_GP_CFG_1(bank, 31, fn, sfx, cfg) #define PORT_GP_32(bank, fn, sfx) PORT_GP_CFG_32(bank, fn, sfx, 0) #define PORT_GP_32_REV(bank, fn, sfx) \ PORT_GP_1(bank, 31, fn, sfx), PORT_GP_1(bank, 30, fn, sfx), \ PORT_GP_1(bank, 29, fn, sfx), PORT_GP_1(bank, 28, fn, sfx), \ PORT_GP_1(bank, 27, fn, sfx), PORT_GP_1(bank, 26, fn, sfx), \ PORT_GP_1(bank, 25, fn, sfx), PORT_GP_1(bank, 24, fn, sfx), \ PORT_GP_1(bank, 23, fn, sfx), PORT_GP_1(bank, 22, fn, sfx), \ PORT_GP_1(bank, 21