X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fgeneric%2Fpatches-3.10%2F020-ssb_update.patch;h=4b0caa806a305993d9a67d50f8471be4697407af;hb=44a1b2d391cc620ac5d9f1698d41f95bb60d9b4f;hp=1605705251273bd5b0162213a3607be4b22c46d2;hpb=13ef6bbc9a55ad194ef2121b1859bf94b218c9f9;p=15.05%2Fopenwrt.git diff --git a/target/linux/generic/patches-3.10/020-ssb_update.patch b/target/linux/generic/patches-3.10/020-ssb_update.patch index 1605705251..4b0caa806a 100644 --- a/target/linux/generic/patches-3.10/020-ssb_update.patch +++ b/target/linux/generic/patches-3.10/020-ssb_update.patch @@ -16,6 +16,14 @@ default y config SSB_DRIVER_EXTIF +@@ -168,6 +168,7 @@ config SSB_DRIVER_GIGE + config SSB_DRIVER_GPIO + bool "SSB GPIO driver" + depends on SSB && GPIOLIB ++ select IRQ_DOMAIN if SSB_EMBEDDED + help + Driver to provide access to the GPIO pins on the bus. + --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c @@ -9,6 +9,19 @@ @@ -47,8 +55,12 @@ { "M25P20", 0x11, 0x10000, 4, }, { "M25P40", 0x12, 0x10000, 8, }, -@@ -27,7 +40,7 @@ static struct ssb_sflash_tbl_e ssb_sflas - { 0 }, +@@ -24,10 +37,10 @@ static struct ssb_sflash_tbl_e ssb_sflas + { "M25P32", 0x15, 0x10000, 64, }, + { "M25P64", 0x16, 0x10000, 128, }, + { "M25FL128", 0x17, 0x10000, 256, }, +- { 0 }, ++ { NULL }, }; -static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { @@ -56,8 +68,12 @@ { "SST25WF512", 1, 0x1000, 16, }, { "SST25VF512", 0x48, 0x1000, 16, }, { "SST25WF010", 2, 0x1000, 32, }, -@@ -45,7 +58,7 @@ static struct ssb_sflash_tbl_e ssb_sflas - { 0 }, +@@ -42,10 +55,10 @@ static struct ssb_sflash_tbl_e ssb_sflas + { "SST25VF016", 0x41, 0x1000, 512, }, + { "SST25VF032", 0x4a, 0x1000, 1024, }, + { "SST25VF064", 0x4b, 0x1000, 2048, }, +- { 0 }, ++ { NULL }, }; -static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { @@ -65,6 +81,15 @@ { "AT45DB011", 0xc, 256, 512, }, { "AT45DB021", 0x14, 256, 1024, }, { "AT45DB041", 0x1c, 256, 2048, }, +@@ -53,7 +66,7 @@ static struct ssb_sflash_tbl_e ssb_sflas + { "AT45DB161", 0x2c, 512, 4096, }, + { "AT45DB321", 0x34, 512, 8192, }, + { "AT45DB642", 0x3c, 1024, 8192, }, +- { 0 }, ++ { NULL }, + }; + + static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) @@ -73,7 +86,8 @@ static void ssb_sflash_cmd(struct ssb_ch /* Initialize serial flash access */ int ssb_sflash_init(struct ssb_chipcommon *cc) @@ -101,6 +126,396 @@ - return -ENOTSUPP; + return 0; } +--- a/drivers/ssb/driver_gpio.c ++++ b/drivers/ssb/driver_gpio.c +@@ -9,16 +9,40 @@ + */ + + #include ++#include ++#include ++#include + #include + #include + + #include "ssb_private.h" + ++ ++/************************************************** ++ * Shared ++ **************************************************/ ++ + static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) + { + return container_of(chip, struct ssb_bus, gpio); + } + ++#if IS_ENABLED(CONFIG_SSB_EMBEDDED) ++static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); ++ ++ if (bus->bustype == SSB_BUSTYPE_SSB) ++ return irq_find_mapping(bus->irq_domain, gpio); ++ else ++ return -EINVAL; ++} ++#endif ++ ++/************************************************** ++ * ChipCommon ++ **************************************************/ ++ + static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) + { + struct ssb_bus *bus = ssb_gpio_get_bus(chip); +@@ -74,19 +98,129 @@ static void ssb_gpio_chipco_free(struct + ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); + } + +-static int ssb_gpio_chipco_to_irq(struct gpio_chip *chip, unsigned gpio) ++#if IS_ENABLED(CONFIG_SSB_EMBEDDED) ++static void ssb_gpio_irq_chipco_mask(struct irq_data *d) + { +- struct ssb_bus *bus = ssb_gpio_get_bus(chip); ++ struct ssb_bus *bus = irq_data_get_irq_chip_data(d); ++ int gpio = irqd_to_hwirq(d); + +- if (bus->bustype == SSB_BUSTYPE_SSB) +- return ssb_mips_irq(bus->chipco.dev) + 2; +- else +- return -EINVAL; ++ ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0); ++} ++ ++static void ssb_gpio_irq_chipco_unmask(struct irq_data *d) ++{ ++ struct ssb_bus *bus = irq_data_get_irq_chip_data(d); ++ int gpio = irqd_to_hwirq(d); ++ u32 val = ssb_chipco_gpio_in(&bus->chipco, BIT(gpio)); ++ ++ ssb_chipco_gpio_polarity(&bus->chipco, BIT(gpio), val); ++ ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), BIT(gpio)); ++} ++ ++static struct irq_chip ssb_gpio_irq_chipco_chip = { ++ .name = "SSB-GPIO-CC", ++ .irq_mask = ssb_gpio_irq_chipco_mask, ++ .irq_unmask = ssb_gpio_irq_chipco_unmask, ++}; ++ ++static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id) ++{ ++ struct ssb_bus *bus = dev_id; ++ struct ssb_chipcommon *chipco = &bus->chipco; ++ u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN); ++ u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ); ++ u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL); ++ unsigned long irqs = (val ^ pol) & mask; ++ int gpio; ++ ++ if (!irqs) ++ return IRQ_NONE; ++ ++ for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) ++ generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio)); ++ ssb_chipco_gpio_polarity(chipco, irqs, val & irqs); ++ ++ return IRQ_HANDLED; ++} ++ ++static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) ++{ ++ struct ssb_chipcommon *chipco = &bus->chipco; ++ struct gpio_chip *chip = &bus->gpio; ++ int gpio, hwirq, err; ++ ++ if (bus->bustype != SSB_BUSTYPE_SSB) ++ return 0; ++ ++ bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, ++ &irq_domain_simple_ops, chipco); ++ if (!bus->irq_domain) { ++ err = -ENODEV; ++ goto err_irq_domain; ++ } ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_create_mapping(bus->irq_domain, gpio); ++ ++ irq_set_chip_data(irq, bus); ++ irq_set_chip_and_handler(irq, &ssb_gpio_irq_chipco_chip, ++ handle_simple_irq); ++ } ++ ++ hwirq = ssb_mips_irq(bus->chipco.dev) + 2; ++ err = request_irq(hwirq, ssb_gpio_irq_chipco_handler, IRQF_SHARED, ++ "gpio", bus); ++ if (err) ++ goto err_req_irq; ++ ++ ssb_chipco_gpio_intmask(&bus->chipco, ~0, 0); ++ chipco_set32(chipco, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO); ++ ++ return 0; ++ ++err_req_irq: ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_find_mapping(bus->irq_domain, gpio); ++ ++ irq_dispose_mapping(irq); ++ } ++ irq_domain_remove(bus->irq_domain); ++err_irq_domain: ++ return err; ++} ++ ++static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) ++{ ++ struct ssb_chipcommon *chipco = &bus->chipco; ++ struct gpio_chip *chip = &bus->gpio; ++ int gpio; ++ ++ if (bus->bustype != SSB_BUSTYPE_SSB) ++ return; ++ ++ chipco_mask32(chipco, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO); ++ free_irq(ssb_mips_irq(bus->chipco.dev) + 2, chipco); ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_find_mapping(bus->irq_domain, gpio); ++ ++ irq_dispose_mapping(irq); ++ } ++ irq_domain_remove(bus->irq_domain); ++} ++#else ++static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) ++{ ++ return 0; ++} ++ ++static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) ++{ + } ++#endif + + static int ssb_gpio_chipco_init(struct ssb_bus *bus) + { + struct gpio_chip *chip = &bus->gpio; ++ int err; + + chip->label = "ssb_chipco_gpio"; + chip->owner = THIS_MODULE; +@@ -96,7 +230,9 @@ static int ssb_gpio_chipco_init(struct s + chip->set = ssb_gpio_chipco_set_value; + chip->direction_input = ssb_gpio_chipco_direction_input; + chip->direction_output = ssb_gpio_chipco_direction_output; +- chip->to_irq = ssb_gpio_chipco_to_irq; ++#if IS_ENABLED(CONFIG_SSB_EMBEDDED) ++ chip->to_irq = ssb_gpio_to_irq; ++#endif + chip->ngpio = 16; + /* There is just one SoC in one device and its GPIO addresses should be + * deterministic to address them more easily. The other buses could get +@@ -106,9 +242,23 @@ static int ssb_gpio_chipco_init(struct s + else + chip->base = -1; + +- return gpiochip_add(chip); ++ err = ssb_gpio_irq_chipco_domain_init(bus); ++ if (err) ++ return err; ++ ++ err = gpiochip_add(chip); ++ if (err) { ++ ssb_gpio_irq_chipco_domain_exit(bus); ++ return err; ++ } ++ ++ return 0; + } + ++/************************************************** ++ * EXTIF ++ **************************************************/ ++ + #ifdef CONFIG_SSB_DRIVER_EXTIF + + static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) +@@ -145,19 +295,127 @@ static int ssb_gpio_extif_direction_outp + return 0; + } + +-static int ssb_gpio_extif_to_irq(struct gpio_chip *chip, unsigned gpio) ++#if IS_ENABLED(CONFIG_SSB_EMBEDDED) ++static void ssb_gpio_irq_extif_mask(struct irq_data *d) + { +- struct ssb_bus *bus = ssb_gpio_get_bus(chip); ++ struct ssb_bus *bus = irq_data_get_irq_chip_data(d); ++ int gpio = irqd_to_hwirq(d); + +- if (bus->bustype == SSB_BUSTYPE_SSB) +- return ssb_mips_irq(bus->extif.dev) + 2; +- else +- return -EINVAL; ++ ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0); ++} ++ ++static void ssb_gpio_irq_extif_unmask(struct irq_data *d) ++{ ++ struct ssb_bus *bus = irq_data_get_irq_chip_data(d); ++ int gpio = irqd_to_hwirq(d); ++ u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio)); ++ ++ ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val); ++ ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio)); ++} ++ ++static struct irq_chip ssb_gpio_irq_extif_chip = { ++ .name = "SSB-GPIO-EXTIF", ++ .irq_mask = ssb_gpio_irq_extif_mask, ++ .irq_unmask = ssb_gpio_irq_extif_unmask, ++}; ++ ++static irqreturn_t ssb_gpio_irq_extif_handler(int irq, void *dev_id) ++{ ++ struct ssb_bus *bus = dev_id; ++ struct ssb_extif *extif = &bus->extif; ++ u32 val = ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN); ++ u32 mask = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTMASK); ++ u32 pol = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTPOL); ++ unsigned long irqs = (val ^ pol) & mask; ++ int gpio; ++ ++ if (!irqs) ++ return IRQ_NONE; ++ ++ for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) ++ generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio)); ++ ssb_extif_gpio_polarity(extif, irqs, val & irqs); ++ ++ return IRQ_HANDLED; ++} ++ ++static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) ++{ ++ struct ssb_extif *extif = &bus->extif; ++ struct gpio_chip *chip = &bus->gpio; ++ int gpio, hwirq, err; ++ ++ if (bus->bustype != SSB_BUSTYPE_SSB) ++ return 0; ++ ++ bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, ++ &irq_domain_simple_ops, extif); ++ if (!bus->irq_domain) { ++ err = -ENODEV; ++ goto err_irq_domain; ++ } ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_create_mapping(bus->irq_domain, gpio); ++ ++ irq_set_chip_data(irq, bus); ++ irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip, ++ handle_simple_irq); ++ } ++ ++ hwirq = ssb_mips_irq(bus->extif.dev) + 2; ++ err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED, ++ "gpio", bus); ++ if (err) ++ goto err_req_irq; ++ ++ ssb_extif_gpio_intmask(&bus->extif, ~0, 0); ++ ++ return 0; ++ ++err_req_irq: ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_find_mapping(bus->irq_domain, gpio); ++ ++ irq_dispose_mapping(irq); ++ } ++ irq_domain_remove(bus->irq_domain); ++err_irq_domain: ++ return err; + } + ++static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) ++{ ++ struct ssb_extif *extif = &bus->extif; ++ struct gpio_chip *chip = &bus->gpio; ++ int gpio; ++ ++ if (bus->bustype != SSB_BUSTYPE_SSB) ++ return; ++ ++ free_irq(ssb_mips_irq(bus->extif.dev) + 2, extif); ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_find_mapping(bus->irq_domain, gpio); ++ ++ irq_dispose_mapping(irq); ++ } ++ irq_domain_remove(bus->irq_domain); ++} ++#else ++static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) ++{ ++ return 0; ++} ++ ++static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) ++{ ++} ++#endif ++ + static int ssb_gpio_extif_init(struct ssb_bus *bus) + { + struct gpio_chip *chip = &bus->gpio; ++ int err; + + chip->label = "ssb_extif_gpio"; + chip->owner = THIS_MODULE; +@@ -165,7 +423,9 @@ static int ssb_gpio_extif_init(struct ss + chip->set = ssb_gpio_extif_set_value; + chip->direction_input = ssb_gpio_extif_direction_input; + chip->direction_output = ssb_gpio_extif_direction_output; +- chip->to_irq = ssb_gpio_extif_to_irq; ++#if IS_ENABLED(CONFIG_SSB_EMBEDDED) ++ chip->to_irq = ssb_gpio_to_irq; ++#endif + chip->ngpio = 5; + /* There is just one SoC in one device and its GPIO addresses should be + * deterministic to address them more easily. The other buses could get +@@ -175,7 +435,17 @@ static int ssb_gpio_extif_init(struct ss + else + chip->base = -1; + +- return gpiochip_add(chip); ++ err = ssb_gpio_irq_extif_domain_init(bus); ++ if (err) ++ return err; ++ ++ err = gpiochip_add(chip); ++ if (err) { ++ ssb_gpio_irq_extif_domain_exit(bus); ++ return err; ++ } ++ ++ return 0; + } + + #else +@@ -185,6 +455,10 @@ static int ssb_gpio_extif_init(struct ss + } + #endif + ++/************************************************** ++ * Init ++ **************************************************/ ++ + int ssb_gpio_init(struct ssb_bus *bus) + { + if (ssb_chipco_available(&bus->chipco)) --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -553,6 +553,14 @@ static int ssb_devices_register(struct s @@ -118,6 +533,32 @@ return 0; error: /* Unwind the already registered devices. */ +@@ -582,6 +590,13 @@ static int ssb_attach_queued_buses(void) + ssb_pcicore_init(&bus->pcicore); + if (bus->bustype == SSB_BUSTYPE_SSB) + ssb_watchdog_register(bus); ++ ++ err = ssb_gpio_init(bus); ++ if (err == -ENOTSUPP) ++ ssb_dbg("GPIO driver not activated\n"); ++ else if (err) ++ ssb_dbg("Error registering GPIO driver: %i\n", err); ++ + ssb_bus_may_powerdown(bus); + + err = ssb_devices_register(bus); +@@ -819,11 +834,6 @@ static int ssb_bus_register(struct ssb_b + ssb_chipcommon_init(&bus->chipco); + ssb_extif_init(&bus->extif); + ssb_mipscore_init(&bus->mipscore); +- err = ssb_gpio_init(bus); +- if (err == -ENOTSUPP) +- ssb_dbg("GPIO driver not activated\n"); +- else if (err) +- ssb_dbg("Error registering GPIO driver: %i\n", err); + err = ssb_fetch_invariants(bus, get_invariants); + if (err) { + ssb_bus_may_powerdown(bus); --- a/drivers/ssb/pcihost_wrapper.c +++ b/drivers/ssb/pcihost_wrapper.c @@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci @@ -153,6 +594,46 @@ #ifdef CONFIG_SSB_DRIVER_EXTIF extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks); extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); +--- a/include/linux/ssb/ssb.h ++++ b/include/linux/ssb/ssb.h +@@ -486,6 +486,7 @@ struct ssb_bus { + #endif /* EMBEDDED */ + #ifdef CONFIG_SSB_DRIVER_GPIO + struct gpio_chip gpio; ++ struct irq_domain *irq_domain; + #endif /* DRIVER_GPIO */ + + /* Internal-only stuff follows. Do not touch. */ +--- a/include/linux/ssb/ssb_driver_gige.h ++++ b/include/linux/ssb/ssb_driver_gige.h +@@ -108,6 +108,16 @@ static inline int ssb_gige_get_macaddr(s + return 0; + } + ++/* Get the device phy address */ ++static inline int ssb_gige_get_phyaddr(struct pci_dev *pdev) ++{ ++ struct ssb_gige *dev = pdev_to_ssb_gige(pdev); ++ if (!dev) ++ return -ENODEV; ++ ++ return dev->dev->bus->sprom.et0phyaddr; ++} ++ + extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev, + struct pci_dev *pdev); + extern int ssb_gige_map_irq(struct ssb_device *sdev, +@@ -174,6 +184,10 @@ static inline int ssb_gige_get_macaddr(s + { + return -ENODEV; + } ++static inline int ssb_gige_get_phyaddr(struct pci_dev *pdev) ++{ ++ return -ENODEV; ++} + + #endif /* CONFIG_SSB_DRIVER_GIGE */ + #endif /* LINUX_SSB_DRIVER_GIGE_H_ */ --- a/include/linux/ssb/ssb_driver_mips.h +++ b/include/linux/ssb/ssb_driver_mips.h @@ -20,6 +20,18 @@ struct ssb_pflash {