mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
brcm43xx: update SSB driver
* files/ now contains the wireless-dev tree version * patches/210-ssb_merge is nbd's subsequent changes git-svn-id: svn://svn.openwrt.org/openwrt/trunk@7691 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
@@ -121,7 +121,7 @@ int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
|
||||
err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
|
||||
if (err)
|
||||
goto err_pci;
|
||||
msleep(2);
|
||||
msleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,52 @@ static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
|
||||
sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2));
|
||||
}
|
||||
|
||||
static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
|
||||
{
|
||||
struct pci_dev *pdev = bus->host_pci;
|
||||
int i, err;
|
||||
u32 spromctl;
|
||||
|
||||
ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
|
||||
err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
|
||||
if (err)
|
||||
goto err_ctlreg;
|
||||
spromctl |= SSB_SPROMCTL_WE;
|
||||
err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
|
||||
if (err)
|
||||
goto err_ctlreg;
|
||||
ssb_printk(KERN_NOTICE PFX "[ 0%%");
|
||||
msleep(500);
|
||||
for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
|
||||
if (i == SSB_SPROMSIZE_WORDS / 4)
|
||||
ssb_printk("25%%");
|
||||
else if (i == SSB_SPROMSIZE_WORDS / 2)
|
||||
ssb_printk("50%%");
|
||||
else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3)
|
||||
ssb_printk("75%%");
|
||||
else if (i % 2)
|
||||
ssb_printk(".");
|
||||
writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
|
||||
mmiowb();
|
||||
msleep(20);
|
||||
}
|
||||
err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
|
||||
if (err)
|
||||
goto err_ctlreg;
|
||||
spromctl &= ~SSB_SPROMCTL_WE;
|
||||
err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
|
||||
if (err)
|
||||
goto err_ctlreg;
|
||||
msleep(500);
|
||||
ssb_printk("100%% ]\n");
|
||||
ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
|
||||
|
||||
return 0;
|
||||
err_ctlreg:
|
||||
ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
|
||||
{
|
||||
int i;
|
||||
@@ -472,9 +518,155 @@ const struct ssb_bus_ops ssb_pci_ops = {
|
||||
.write32 = ssb_pci_write32,
|
||||
};
|
||||
|
||||
static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
|
||||
{
|
||||
int i, pos = 0;
|
||||
|
||||
for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
|
||||
pos += snprintf(buf + pos, buf_len - pos - 1,
|
||||
"%04X", swab16(sprom[i]) & 0xFFFF);
|
||||
}
|
||||
pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
|
||||
|
||||
return pos + 1;
|
||||
}
|
||||
|
||||
static int hex2sprom(u16 *sprom, const char *dump, size_t len)
|
||||
{
|
||||
char tmp[5] = { 0 };
|
||||
int cnt = 0;
|
||||
unsigned long parsed;
|
||||
|
||||
if (len < SSB_SPROMSIZE_BYTES * 2)
|
||||
return -EINVAL;
|
||||
|
||||
while (cnt < SSB_SPROMSIZE_WORDS) {
|
||||
memcpy(tmp, dump, 4);
|
||||
dump += 4;
|
||||
parsed = simple_strtoul(tmp, NULL, 16);
|
||||
sprom[cnt++] = swab16((u16)parsed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
|
||||
struct ssb_bus *bus;
|
||||
u16 *sprom;
|
||||
int err = -ENODEV;
|
||||
ssize_t count = 0;
|
||||
|
||||
bus = ssb_pci_dev_to_bus(pdev);
|
||||
if (!bus)
|
||||
goto out;
|
||||
err = -ENOMEM;
|
||||
sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
|
||||
if (!sprom)
|
||||
goto out;
|
||||
|
||||
err = -ERESTARTSYS;
|
||||
if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
|
||||
goto out_kfree;
|
||||
sprom_do_read(bus, sprom);
|
||||
mutex_unlock(&bus->pci_sprom_mutex);
|
||||
|
||||
count = sprom2hex(sprom, buf, PAGE_SIZE);
|
||||
err = 0;
|
||||
|
||||
out_kfree:
|
||||
kfree(sprom);
|
||||
out:
|
||||
return err ? err : count;
|
||||
}
|
||||
|
||||
static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
|
||||
struct ssb_bus *bus;
|
||||
u16 *sprom;
|
||||
int res = 0, err = -ENODEV;
|
||||
|
||||
bus = ssb_pci_dev_to_bus(pdev);
|
||||
if (!bus)
|
||||
goto out;
|
||||
err = -ENOMEM;
|
||||
sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
|
||||
if (!sprom)
|
||||
goto out;
|
||||
err = hex2sprom(sprom, buf, count);
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
goto out_kfree;
|
||||
}
|
||||
err = sprom_check_crc(sprom);
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
err = -ERESTARTSYS;
|
||||
if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
|
||||
goto out_kfree;
|
||||
err = ssb_devices_freeze(bus);
|
||||
if (err) {
|
||||
ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
res = sprom_do_write(bus, sprom);
|
||||
err = ssb_devices_thaw(bus);
|
||||
if (err)
|
||||
ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
|
||||
out_unlock:
|
||||
mutex_unlock(&bus->pci_sprom_mutex);
|
||||
out_kfree:
|
||||
kfree(sprom);
|
||||
out:
|
||||
if (res)
|
||||
return res;
|
||||
return err ? err : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(ssb_sprom, 0600,
|
||||
ssb_pci_attr_sprom_show,
|
||||
ssb_pci_attr_sprom_store);
|
||||
|
||||
void ssb_pci_exit(struct ssb_bus *bus)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (bus->bustype != SSB_BUSTYPE_PCI)
|
||||
return;
|
||||
|
||||
pdev = bus->host_pci;
|
||||
device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
|
||||
}
|
||||
|
||||
int ssb_pci_init(struct ssb_bus *bus)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
int err;
|
||||
|
||||
if (bus->bustype != SSB_BUSTYPE_PCI)
|
||||
return 0;
|
||||
return ssb_pci_sprom_get(bus);
|
||||
|
||||
pdev = bus->host_pci;
|
||||
mutex_init(&bus->pci_sprom_mutex);
|
||||
err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
|
||||
if (err)
|
||||
goto out;
|
||||
err = ssb_pci_sprom_get(bus);
|
||||
if (err)
|
||||
goto err_remove_sprom_file;
|
||||
|
||||
out:
|
||||
return err;
|
||||
err_remove_sprom_file:
|
||||
device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user