Hi Pieter,

On Wed, May 09, 2012 at 08:41:41AM +0200, Pieter Voorthuijsen wrote:
> WIFI eeprom:
> As discussed, it is impossible for nand and spi flash platforms to have the 
> eeprom data available from mtd. I suggested to load the eeprom from 
> user-space. I've looked into regular firmware loading but this is only 
> possible when using modules.  I've created a sysfs entry that allows reading 
> and writing the eeprom data to the platform data. After loading the eeprom 
> data I rely on pci-hotplug support to disable the bogus pci device and rescan 
> the bus (with fixups and all). Because hotplug is not available, an init 
> script is created that performs the copy from mtd to platform data. I think 
> it is best to eventually move the sysfs functions to dev_wifi_athxk.c file, 
> this would get rid of the external to the ath9k platform data.
> 
> SPI flash:
> It seems that the spi-xway driver is not really working. It causes my kernel 
> to crash in all sorts of ways. I added to bitbang SPI to be able to the 
> calibration data mention above.
> I've kept the original mtd partitioning that Netgear uses.
> 
> Buttons/LED:
> Both buttons are working properly. Two leds are not enabled: The red internet 
> led is connected to the pci_gnt1 pin... I can't disable it because then DMA 
> stops working.
> The green wifi led is connected to an unknown atheros gpio.
> 
> Signed-off-by: Pieter Voorthuijsen <p.voorthuijsen at gmail.com>
> ---
> 
> Index: target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c
> ===================================================================
> --- target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c        
> (revision 31548)
> +++ target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c        
> (working copy)
> @@ -4,6 +4,7 @@
>   *  by the Free Software Foundation.
>   *
>   *  Copyright (C) 2010 John Crispin <blo...@openwrt.org>
> + *  Copyright (C) 2012 Pieter Voorthuijsen
>   */
> 
>  #include <linux/init.h>
> @@ -15,14 +16,31 @@
>  #include <linux/phy.h>
>  #include <linux/spi/spi.h>
>  #include <linux/spi/flash.h>
> +#include <linux/spi/spi_gpio.h>
> +#include <linux/ath9k_platform.h>
> +#include <linux/if_ether.h>
> +#include <linux/etherdevice.h>
> +#include <linux/kobject.h>
> +#include <linux/sysfs.h>
> 
>  #include <lantiq_soc.h>
>  #include <irq.h>
> +#include <dev-gpio-leds.h>
> +#include <dev-gpio-buttons.h>
> +#include "dev-wifi-athxk.h"
> 
>  #include "../machtypes.h"
>  #include "devices.h"
>  #include "dev-dwc_otg.h"
> +#include "pci-ath-fixup.h"
> +#include <mtd/mtd-abi.h>
> +#include <asm-generic/sizes.h>
> 
> +#define SPI_GPIO_MRST   16
> +#define SPI_GPIO_MTSR   17
> +#define SPI_GPIO_CLK    18
> +#define SPI_GPIO_CS0    10
> +
>  static struct ltq_pci_data ltq_pci_data = {
>       .clock  = PCI_CLOCK_INT,
>       .gpio   = PCI_GNT1 | PCI_REQ1,
> @@ -35,49 +53,221 @@
>       .mii_mode = PHY_INTERFACE_MODE_MII,
>  };
> 
> -static struct mtd_partition easy98000_nor_partitions[] =
> -{

Usually partition information is on top...

> +static struct gpio_led
> +dgn3500_gpio_leds[] __initdata = {
> +     { .name = "soc:green:power", .gpio = 34, .active_low = 1, },
> +     { .name = "soc:red:power", .gpio = 39, .active_low = 1, },
> +     /* Green WLAN can be controlled via ath or alt setting ?? */
> +     /*{ .name = "soc:green:wlan", .gpio = 10, .active_low = 1, }, */
> +     { .name = "soc:orange:wlan", .gpio = 51, .active_low = 1, },
> +     { .name = "soc:green:wps", .gpio = 52, .active_low = 1, },
> +     { .name = "soc:green:usb", .gpio = 22, .active_low = 1, },
> +     { .name = "soc:green:dsl", .gpio = 4, .active_low = 1, },
> +     { .name = "soc:green:internet", .gpio = 2, .active_low = 1, },
> +     /* Red internet is in use by PCI GNT1 signal?? */
> +     /*{ .name = "soc:red:internet", .gpio = 30, .active_low = 1, }*/
> +};
> +
> +static struct gpio_keys_button
> +dgn3500_gpio_keys[] __initdata = {
>       {
> -             .name   = "uboot",
> -             .offset = 0x0,
> -             .size   = 0x40000,
> +             .desc = "wps",
> +             .type = EV_KEY,
> +             .code = BTN_0,
> +             .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
> +             .gpio = 54,
> +             .active_low = 1,
>       },
>       {
> -             .name   = "uboot_env",
> -             .offset = 0x40000,
> -             .size   = 0x40000,      /* 2 sectors for redundant env. */
> +             .desc = "reset",
> +             .type = EV_KEY,
> +             .code = BTN_1,
> +             .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
> +             .gpio = 36,
> +             .active_low = 1,
>       },
> +};
> +
> +static struct mtd_partition dgn3500_partitions[] = {
>       {
> -             .name   = "linux",
> -             .offset = 0x80000,
> -             .size   = 0xF80000,     /* map only 16 MiB */
> +             .name = "u-boot",
> +             .offset = 0,
> +             .size = SZ_64K,

I prefer the old way of defining this. If we are going to use this we
should change all lantiq targets.

> +             .mask_flags = MTD_WRITEABLE,

I think we do not need to define this.

>       },
> +     {
> +             .name = "environment",
> +             .offset = MTDPART_OFS_APPEND,
> +             .size = SZ_64K,
> +             .mask_flags = MTD_WRITEABLE,
> +     },
> +     {
> +             .name = "dpf",

Can you tell us why we need this partition?

> +             .offset = MTDPART_OFS_APPEND,
> +             .size = SZ_64K,
> +             .mask_flags = MTD_WRITEABLE,
> +     },
> +     {
> +             .name = "nvram",

Can you tell us why we need this partition?

> +             .offset = MTDPART_OFS_APPEND,
> +             .size = SZ_128K,
> +             .mask_flags = MTD_WRITEABLE,
> +     },
> +     {
> +             .name = "linux",
> +             .offset = MTDPART_OFS_APPEND,
> +             .size = SZ_1K * 12800,
> +     },
> +     {
> +             .name = "uilang",

Can you tell us why we need this partition?

> +             .offset = MTDPART_OFS_APPEND,
> +             .size = SZ_1M * 3,
> +     },
> +     {
> +             .name = "tm",

Can you tell us why we need this partition?

> +             .offset = MTDPART_OFS_APPEND,
> +             .size = SZ_128K,
> +             .mask_flags = MTD_WRITEABLE,
> +     },
> +     {
> +             .name = "pot",

Can you tell us why we need this partition?

> +             .offset = MTDPART_OFS_APPEND,
> +             .size = SZ_64K,
> +             .mask_flags = MTD_WRITEABLE,
> +     },
> +     {
> +             .name = "entire_flash",

No need for this.

> +             .offset = 0,
> +             .size = SZ_16M,
> +             .mask_flags = MTD_WRITEABLE,
> +     },
>  };
> 
> -static struct flash_platform_data easy98000_spi_flash_platform_data = {
> -     .name = "sflash",
> -     .parts = easy98000_nor_partitions,
> -     .nr_parts = ARRAY_SIZE(easy98000_nor_partitions)
> +static struct spi_gpio_platform_data spi_gpio_data = {
> +     .sck            = SPI_GPIO_CLK,
> +     .mosi           = SPI_GPIO_MTSR,
> +     .miso           = SPI_GPIO_MRST,
> +     .num_chipselect = 2,
>  };
> 
> -static struct spi_board_info spi_info __initdata = {
> -     .modalias               = "m25p80",
> -     .bus_num                = 0,
> -     .chip_select            = 3,
> -     .max_speed_hz           = 10 * 1000 * 1000,
> -     .mode                   = SPI_MODE_3,
> -     .platform_data          = &easy98000_spi_flash_platform_data
> +static struct platform_device spi_gpio_device = {
> +     .name                   = "spi_gpio",
> +     .dev.platform_data      = &spi_gpio_data,
>  };
> 
> -struct ltq_spi_platform_data ltq_spi_data = {
> -     .num_chipselect = 4,
> +static struct flash_platform_data spi_flash_data = {
> +     .name           = "sflash",
> +     .parts          = dgn3500_partitions,
> +     .nr_parts       = ARRAY_SIZE(dgn3500_partitions),
>  };
> 
> +static struct spi_board_info spi_flash __initdata = {
> +     .modalias               = "m25p80",
> +     .bus_num                = 0,
> +     .chip_select            = 0,
> +     .max_speed_hz           = 10 * 1000 * 1000,
> +     .mode                   = SPI_MODE_3,
> +     .chip_select            = 0,
> +     .controller_data        = (void *) SPI_GPIO_CS0,
> +     .platform_data          = &spi_flash_data
> +};
> +
> +static u8 ltq_ethaddr[6] = { 0 };
> +
> +static int __init setup_ethaddr(char *str)
> +{
> +     if (!mac_pton(str, ltq_ethaddr))
> +             memset(ltq_ethaddr, 0, 6);

What if mac address is not passed to kernel when booting?

> +     return 0;
> +}
> +__setup("ethaddr=", setup_ethaddr);
> +
> +static u16 dgn3500_eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS] = {0};
> +
> +static ssize_t ath_eeprom_read(struct file *filp, struct kobject *kobj,
> +             struct bin_attribute *attr, char *buf,
> +             loff_t offset, size_t count)
> +{
> +     if (unlikely(offset >= sizeof(dgn3500_eeprom_data)))
> +             return 0;
> +     if ((offset + count) > sizeof(dgn3500_eeprom_data))
> +             count = sizeof(dgn3500_eeprom_data) - offset;
> +     if (unlikely(!count))
> +             return count;
> +
> +     memcpy(buf, (char *)(dgn3500_eeprom_data) + offset, count);
> +
> +     return count;
> +}
> +
> +extern struct ath9k_platform_data ath9k_pdata;
> +
> +static ssize_t ath_eeprom_write(struct file *filp, struct kobject *kobj,
> +             struct bin_attribute *attr, char *buf,
> +             loff_t offset, size_t count)
> +{
> +     int i;
> +     char *eeprom_bytes = (char *)dgn3500_eeprom_data;
> +
> +     if (unlikely(offset >= sizeof(dgn3500_eeprom_data)))
> +             return -EFBIG;
> +     if ((offset + count) > sizeof(dgn3500_eeprom_data))
> +             count = sizeof(dgn3500_eeprom_data) - offset;
> +     if (unlikely(!count))
> +             return count;
> +     if (count % 2)
> +             return 0;
> +
> +     /* The PCI fixup routine requires an endian swap of the calibartion data
> +      * stored in flash */
> +     for (i = 0; i < count; i += 2) {
> +             eeprom_bytes[offset + i + 1] = buf[i];
> +             eeprom_bytes[offset + i] = buf[i+1];
> +     }
> +
> +     /* The original data does not contain a checksum. Set the country and
> +      * calculate new checksum when all data is received */
> +     if ((count + offset) == sizeof(dgn3500_eeprom_data))
> +             memcpy(ath9k_pdata.eeprom_data, dgn3500_eeprom_data,
> +                             sizeof(ath9k_pdata.eeprom_data));
> +
> +     return count;
> +}
> +
> +static struct bin_attribute dev_attr_ath_eeprom = {
> +     .attr = {
> +             .name = "ath_eeprom",
> +             .mode = S_IRUGO|S_IWUSR,
> +     },
> +     .read = ath_eeprom_read,
> +     .write = ath_eeprom_write,
> +};
> +
>  static void __init dgn3500_init(void)
>  {
> +     if (!sysfs_create_bin_file(firmware_kobj, &dev_attr_ath_eeprom))
> +             printk(KERN_INFO "failed to create sysfs entry firm ath 
> eeprom\n");
> +
> +     ltq_add_device_gpio_leds(-1, ARRAY_SIZE(dgn3500_gpio_leds),
> +                     dgn3500_gpio_leds);
> +     ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
> +                     ARRAY_SIZE(dgn3500_gpio_keys), dgn3500_gpio_keys);
> +
> +     platform_device_register(&spi_gpio_device);
> +
>       ltq_register_pci(&ltq_pci_data);
> +     spi_register_board_info(&spi_flash, 1);
> +
> +     if (!is_valid_ether_addr(ltq_ethaddr)) {
> +             printk(KERN_INFO "mac address not present or invalid,"\
> +                     "using random\n");
> +             random_ether_addr(ltq_ethaddr);
> +     }
> +     memcpy(&ltq_eth_data.mac.sa_data, ltq_ethaddr, 6);
>       ltq_register_etop(&ltq_eth_data);
> -     ltq_register_spi(&ltq_spi_data, &spi_info, 1);
> +     ltq_register_ath9k(dgn3500_eeprom_data, ltq_ethaddr);
> +     ltq_pci_ath_fixup(14, dgn3500_eeprom_data);
> +
>       /* The usb power is always enabled, protected by a fuse */
>       xway_register_dwc(-1);
>  }
> Index: target/linux/lantiq/config-3.2
> ===================================================================
> --- target/linux/lantiq/config-3.2    (revision 31548)
> +++ target/linux/lantiq/config-3.2    (working copy)
> @@ -57,6 +57,9 @@
>  CONFIG_HAVE_IRQ_WORK=y
>  CONFIG_HAVE_OPROFILE=y
>  CONFIG_HAVE_PERF_EVENTS=y
> +CONFIG_HOTPLUG_PCI=y
> +CONFIG_HOTPLUG_PCI_FAKE=y
> +CONFIG_HW_HAS_PCI=y
>  CONFIG_HW_RANDOM=y
>  CONFIG_HZ=250
>  # CONFIG_HZ_100 is not set
> @@ -83,11 +86,15 @@
>  CONFIG_MTD_CFI_ADV_OPTIONS=y
>  CONFIG_MTD_CFI_GEOMETRY=y
>  CONFIG_MTD_CMDLINE_PARTS=y
> +CONFIG_MTD_M25P80=y
>  CONFIG_MTD_LANTIQ=y
>  CONFIG_MTD_UIMAGE_SPLIT=y
>  CONFIG_NEED_DMA_MAP_STATE=y
>  CONFIG_NEED_PER_CPU_KM=y
>  CONFIG_PAGEFLAGS_EXTENDED=y
> +CONFIG_PCI=y
> +CONFIG_PCI_DOMAINS=y
> +CONFIG_PCI_LANTIQ_NONE=y
>  CONFIG_PERF_USE_VMALLOC=y
>  CONFIG_PHYLIB=y
>  # CONFIG_PREEMPT_RCU is not set
> @@ -99,6 +106,11 @@
>  CONFIG_SERIAL_LANTIQ=y
>  CONFIG_SWAP_IO_SPACE=y
>  CONFIG_SWCONFIG=y
> +CONFIG_SPI=y
> +CONFIG_SPI_BITBANG=y
> +CONFIG_SPI_GPIO=y
> +CONFIG_SPI_MASTER=y
> +CONFIG_SWAP_IO_SPACE=y
>  CONFIG_SYS_HAS_CPU_MIPS32_R1=y
>  CONFIG_SYS_HAS_CPU_MIPS32_R2=y
>  CONFIG_SYS_HAS_EARLY_PRINTK=y
> Index: target/linux/lantiq/base-files/lib/preinit/42_athfix
> ===================================================================
> --- target/linux/lantiq/base-files/lib/preinit/42_athfix      (revision 0)
> +++ target/linux/lantiq/base-files/lib/preinit/42_athfix      (revision 0)
> @@ -0,0 +1,19 @@
> +#!/bin/sh
> +
> +. /lib/lantiq.sh
> +
> +init_atheeprom() {
> +     local board=$(lantiq_board_name)
> +     case $board in
> +     "Netgear DGN3500B")
> +             echo "- loading eeprom -"
> +             dd if=/dev/mtd2 of=/sys/firmware/ath_eeprom bs=1k skip=60 
> count=4
> +             echo 0 > /sys/bus/pci/slots/0000\:00\:0e.0/power
> +             sleep 1
> +             echo 1 > /sys/bus/pci/rescan
> +             ;;
> +     esac
> +}
> +
> +boot_hook_add preinit_essential init_atheeprom

Regards,
Luka

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to