From 897bf1c78c2db2d67b19382e0166a697377ddff9 Mon Sep 17 00:00:00 2001 From: neal tai Date: Tue, 27 Feb 2018 14:31:51 +0800 Subject: [PATCH] [Delta]: Modify delta-ag9032v1 driver for kernel 4.9 Signed-off-by: neal tai --- platform/broadcom/rules.mk | 2 +- .../ag9032v1/modules/Makefile | 2 +- .../ag9032v1/modules/at24.c | 698 ------------------ .../modules/delta_ag9032v1_platform.c | 219 +++++- .../ag9032v1/modules/dni_ag9032v1_psu.c | 7 +- .../debian/control | 2 +- .../debian/platform-modules-ag9032v1.install | 1 + .../sonic-platform-modules-delta/debian/rules | 2 +- .../systemd/platform-modules-ag9032v1.service | 13 + 9 files changed, 218 insertions(+), 728 deletions(-) delete mode 100644 platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/at24.c create mode 100644 platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk index eff7236da249..a065506a4287 100755 --- a/platform/broadcom/rules.mk +++ b/platform/broadcom/rules.mk @@ -7,7 +7,7 @@ include $(PLATFORM_PATH)/platform-modules-ingrasys.mk include $(PLATFORM_PATH)/platform-modules-accton.mk include $(PLATFORM_PATH)/platform-modules-inventec.mk include $(PLATFORM_PATH)/platform-modules-cel.mk -#include $(PLATFORM_PATH)/platform-modules-delta.mk +include $(PLATFORM_PATH)/platform-modules-delta.mk include $(PLATFORM_PATH)/platform-modules-quanta.mk #include $(PLATFORM_PATH)/platform-modules-mitac.mk include $(PLATFORM_PATH)/docker-orchagent-brcm.mk diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile index 69b3b48885d3..3dfe4ccb432f 100644 --- a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile @@ -1,2 +1,2 @@ -obj-m := at24.o dni_ag9032v1_psu.o dni_emc2305.o delta_ag9032v1_platform.o +obj-m := dni_ag9032v1_psu.o dni_emc2305.o delta_ag9032v1_platform.o diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/at24.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/at24.c deleted file mode 100644 index 8e73691647d8..000000000000 --- a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/at24.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - * at24.c - handle most I2C EEPROMs - * - * Copyright (C) 2005-2007 David Brownell - * Copyright (C) 2008 Wolfram Sang, Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. - * Differences between different vendor product lines (like Atmel AT24C or - * MicroChip 24LC, etc) won't much matter for typical read/write access. - * There are also I2C RAM chips, likewise interchangeable. One example - * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). - * - * However, misconfiguration can lose data. "Set 16-bit memory address" - * to a part with 8-bit addressing will overwrite data. Writing with too - * big a page size also loses data. And it's not safe to assume that the - * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC - * uses 0x51, for just one example. - * - * Accordingly, explicit board-specific configuration data should be used - * in almost all cases. (One partial exception is an SMBus used to access - * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) - * - * So this driver uses "new style" I2C driver binding, expecting to be - * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or - * similar kernel-resident tables; or, configuration data coming from - * a bootloader. - * - * Other than binding model, current differences from "eeprom" driver are - * that this one handles write access and isn't restricted to 24c02 devices. - * It also handles larger devices (32 kbit and up) with two-byte addresses, - * which won't work on pure SMBus systems. - */ - -struct at24_data { - struct at24_platform_data chip; - struct memory_accessor macc; - int use_smbus; - - /* - * Lock protects against activities from other Linux tasks, - * but not from changes by other I2C masters. - */ - struct mutex lock; - struct bin_attribute bin; - - u8 *writebuf; - unsigned write_max; - unsigned num_addresses; - - /* - * Some chips tie up multiple I2C addresses; dummy devices reserve - * them for us, and we'll use them with SMBus calls. - */ - struct i2c_client *client[]; -}; - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned io_limit = 32; -module_param(io_limit, uint, 0); -MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 32)"); - -/* - * Specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned write_timeout = 25; -module_param(write_timeout, uint, 0); -MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); - -#define AT24_SIZE_BYTELEN 5 -#define AT24_SIZE_FLAGS 8 - -#define AT24_BITMASK(x) (BIT(x) - 1) - -/* create non-zero magic value for given eeprom parameters */ -#define AT24_DEVICE_MAGIC(_len, _flags) \ - ((1 << AT24_SIZE_FLAGS | (_flags)) \ - << AT24_SIZE_BYTELEN | ilog2(_len)) - -static const struct i2c_device_id at24_ids[] = { - /* needs 8 addresses as A0-A2 are ignored */ - { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) }, - /* old variants can't be handled with this generic entry! */ - { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) }, - { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) }, - /* spd is a 24c02 in memory DIMMs */ - { "spd", AT24_DEVICE_MAGIC(2048 / 8, - AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, - { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) }, - /* 24rf08 quirk is handled at i2c-core */ - { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) }, - { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) }, - { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, - { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, - { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) }, - { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) }, - { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) }, - { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) }, - { "at24", 0 }, - { /* END OF LIST */ } -}; -MODULE_DEVICE_TABLE(i2c, at24_ids); - -/*-------------------------------------------------------------------------*/ - -/* - * This routine supports chips which consume multiple I2C addresses. It - * computes the addressing information to be used for a given r/w request. - * Assumes that sanity checks for offset happened at sysfs-layer. - */ -static struct i2c_client *at24_translate_offset(struct at24_data *at24, - unsigned *offset) -{ - unsigned i; - - if (at24->chip.flags & AT24_FLAG_ADDR16) { - i = *offset >> 16; - *offset &= 0xffff; - } else { - i = *offset >> 8; - *offset &= 0xff; - } - - return at24->client[i]; -} - -static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, - unsigned offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - struct i2c_client *client; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - /* - * REVISIT some multi-address chips don't rollover page reads to - * the next slave address, so we may need to truncate the count. - * Those chips might need another quirk flag. - * - * If the real hardware used four adjacent 24c02 chips and that - * were misconfigured as one 24c08, that would be a similar effect: - * one "eeprom" file not four, but larger reads would fail when - * they crossed certain pages. - */ - - /* - * Slave address and byte offset derive from the offset. Always - * set the byte address; on a multi-master board, another master - * may have changed the chip's "current" address pointer. - */ - client = at24_translate_offset(at24, &offset); - - if (count > io_limit) - count = io_limit; - - switch (at24->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /* Smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. Note that read page rollover helps us - * here (unlike writes). msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - if (at24->chip.flags & AT24_FLAG_ADDR16) - msgbuf[i++] = offset >> 8; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - switch (at24->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t at24_read(struct at24_data *at24, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) - return count; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&at24->lock); - - while (count) { - ssize_t status; - - status = at24_eeprom_read(at24, buf, off, count); - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&at24->lock); - - return retval; -} - -static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct at24_data *at24; - - at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); - return at24_read(at24, buf, off, count); -} - - -/* - * Note that if the hardware write-protect pin is pulled high, the whole - * chip is normally write protected. But there are plenty of product - * variants here, including OTP fuses and partial chip protect. - * - * We only use page mode writes; the alternative is sloooow. This routine - * writes at most one page. - */ -static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, - unsigned offset, size_t count) -{ - struct i2c_client *client; - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned next_page; - - /* Get corresponding I2C address and adjust offset */ - client = at24_translate_offset(at24, &offset); - - /* write_max is at most a page */ - if (count > at24->write_max) - count = at24->write_max; - - /* Never roll over backwards, to the start of this page */ - next_page = roundup(offset + 1, at24->chip.page_size); - if (offset + count > next_page) - count = next_page - offset; - - /* If we'll use I2C calls for I/O, set up the message */ - if (!at24->use_smbus) { - int i = 0; - - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = at24->writebuf; - if (at24->chip.flags & AT24_FLAG_ADDR16) - msg.buf[i++] = offset >> 8; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - } - - /* - * Writes fail if the previous one didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - if (at24->use_smbus) { - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - } else { - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - } - dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", - count, offset, status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, - size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) - return count; - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&at24->lock); - - while (count) { - ssize_t status; - - status = at24_eeprom_write(at24, buf, off, count); - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&at24->lock); - - return retval; -} - -static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct at24_data *at24; - - if (unlikely(off >= attr->size)) - return -EFBIG; - - at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); - return at24_write(at24, buf, off, count); -} - -/*-------------------------------------------------------------------------*/ - -/* - * This lets other kernel code access the eeprom data. For example, it - * might hold a board's Ethernet address, or board-specific calibration - * data generated on the manufacturing floor. - */ - -static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf, - off_t offset, size_t count) -{ - struct at24_data *at24 = container_of(macc, struct at24_data, macc); - - return at24_read(at24, buf, offset, count); -} - -static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf, - off_t offset, size_t count) -{ - struct at24_data *at24 = container_of(macc, struct at24_data, macc); - - return at24_write(at24, buf, offset, count); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_OF -static void at24_get_ofdata(struct i2c_client *client, - struct at24_platform_data *chip) -{ - const __be32 *val; - struct device_node *node = client->dev.of_node; - - if (node) { - if (of_get_property(node, "read-only", NULL)) - chip->flags |= AT24_FLAG_READONLY; - val = of_get_property(node, "pagesize", NULL); - if (val) - chip->page_size = be32_to_cpup(val); - } -} -#else -static void at24_get_ofdata(struct i2c_client *client, - struct at24_platform_data *chip) -{ } -#endif /* CONFIG_OF */ - -static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct at24_platform_data chip; - bool writable; - int use_smbus = 0; - struct at24_data *at24; - int err; - unsigned i, num_addresses; - kernel_ulong_t magic; - - if (client->dev.platform_data) { - chip = *(struct at24_platform_data *)client->dev.platform_data; - } else { - if (!id->driver_data) - return -ENODEV; - - magic = id->driver_data; - chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); - magic >>= AT24_SIZE_BYTELEN; - chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); - /* - * This is slow, but we can't know all eeproms, so we better - * play safe. Specifying custom eeprom-types via platform_data - * is recommended anyhow. - */ - chip.page_size = 1; - - /* update chipdata if OF is present */ - at24_get_ofdata(client, &chip); - - chip.setup = NULL; - chip.context = NULL; - } - - if (!is_power_of_2(chip.byte_len)) - dev_warn(&client->dev, - "byte_len looks suspicious (no power of 2)!\n"); - if (!chip.page_size) { - dev_err(&client->dev, "page_size must not be 0!\n"); - return -EINVAL; - } - if (!is_power_of_2(chip.page_size)) - dev_warn(&client->dev, - "page_size looks suspicious (no power of 2)!\n"); - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (chip.flags & AT24_FLAG_ADDR16) - return -EPFNOSUPPORT; - - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - return -EPFNOSUPPORT; - } - } - - if (chip.flags & AT24_FLAG_TAKE8ADDR) - num_addresses = 8; - else - num_addresses = DIV_ROUND_UP(chip.byte_len, - (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); - - at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + - num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); - if (!at24) - return -ENOMEM; - - mutex_init(&at24->lock); - at24->use_smbus = use_smbus; - at24->chip = chip; - at24->num_addresses = num_addresses; - - /* - * Export the EEPROM bytes through sysfs, since that's convenient. - * By default, only root should see the data (maybe passwords etc) - */ - sysfs_bin_attr_init(&at24->bin); - at24->bin.attr.name = "eeprom"; - at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; - at24->bin.read = at24_bin_read; - at24->bin.size = chip.byte_len; - - at24->macc.read = at24_macc_read; - - writable = !(chip.flags & AT24_FLAG_READONLY); - if (writable) { - if (!use_smbus || i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { - - unsigned write_max = chip.page_size; - - at24->macc.write = at24_macc_write; - - at24->bin.write = at24_bin_write; - at24->bin.attr.mode |= S_IWUSR; - - if (write_max > io_limit) - write_max = io_limit; - if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - at24->write_max = write_max; - - /* buffer (data + address at the beginning) */ - at24->writebuf = devm_kzalloc(&client->dev, - write_max + 2, GFP_KERNEL); - if (!at24->writebuf) - return -ENOMEM; - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - } - - at24->client[0] = client; - - /* use dummy devices for multiple-address chips */ - for (i = 1; i < num_addresses; i++) { - at24->client[i] = i2c_new_dummy(client->adapter, - client->addr + i); - if (!at24->client[i]) { - dev_err(&client->dev, "address 0x%02x unavailable\n", - client->addr + i); - err = -EADDRINUSE; - goto err_clients; - } - } - - err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); - if (err) - goto err_clients; - - i2c_set_clientdata(client, at24); - - dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n", - at24->bin.size, client->name, - writable ? "writable" : "read-only", at24->write_max); - if (use_smbus == I2C_SMBUS_WORD_DATA || - use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } - - /* export data to kernel code */ - if (chip.setup) - chip.setup(&at24->macc, chip.context); - - return 0; - -err_clients: - for (i = 1; i < num_addresses; i++) - if (at24->client[i]) - i2c_unregister_device(at24->client[i]); - - return err; -} - -static int at24_remove(struct i2c_client *client) -{ - struct at24_data *at24; - int i; - - at24 = i2c_get_clientdata(client); - sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); - - for (i = 1; i < at24->num_addresses; i++) - i2c_unregister_device(at24->client[i]); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static struct i2c_driver at24_driver = { - .driver = { - .name = "at24", - .owner = THIS_MODULE, - }, - .probe = at24_probe, - .remove = at24_remove, - .id_table = at24_ids, -}; - -static int __init at24_init(void) -{ - if (!io_limit) { - pr_err("at24: io_limit must not be 0!\n"); - return -EINVAL; - } - - io_limit = rounddown_pow_of_two(io_limit); - return i2c_add_driver(&at24_driver); -} -module_init(at24_init); - -static void __exit at24_exit(void) -{ - i2c_del_driver(&at24_driver); -} -module_exit(at24_exit); - -MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); -MODULE_AUTHOR("David Brownell and Wolfram Sang"); -MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c index 90454a5bdb4a..1b971bc3c133 100644 --- a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c @@ -246,25 +246,25 @@ static struct i2c_device_platform_data ag9032v1_i2c_device_platform_data[] = { { /* psu 1 (0x58) */ .parent = 40, - .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = 0 }, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = (void *) 0 }, .client = NULL, }, { /* psu 2 (0x58) */ .parent = 41, - .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = 1 }, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = (void *) 1 }, .client = NULL, }, { /* hot-swap 1 (0x40) */ .parent = 42, - .info = { .type = "ltc4215", .addr = 0x40, .platform_data = 0 }, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = (void *) 0 }, .client = NULL, }, { /* hot-swap 2 (0x40) */ .parent = 43, - .info = { .type = "ltc4215", .addr = 0x40, .platform_data = 1 }, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = (void *) 1 }, .client = NULL, }, { @@ -607,22 +607,22 @@ static ssize_t get_present(struct device *dev, struct device_attribute \ ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_1); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data = (u32)reverse_8bits(ret) & 0xff; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_2); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 8; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_3); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 16; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_4); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 24; return sprintf(buf, "0x%08x\n", data); //return 32bits data @@ -636,22 +636,22 @@ static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_1); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data = (u32)(reverse_8bits(ret) & 0xff); ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_2); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 8; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_3); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 16; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_4); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 24; return sprintf(buf, "0x%08x\n", data); //return 32bits data @@ -683,22 +683,22 @@ static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, c ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_1); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data = (u32)(reverse_8bits(ret) & 0xff); ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_2); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 8; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_3); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 16; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_4); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 24; return sprintf(buf, "0x%08x\n", data); //return 32bits data @@ -730,22 +730,22 @@ static ssize_t get_response(struct device *dev, struct device_attribute *devattr ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_1); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data = (u32)(reverse_8bits(ret) & 0xff); ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_2); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 8; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_3); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 16; ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_4); if (ret < 0) - return sprintf(buf, "error number(%ld)",ret); + return sprintf(buf, "error number(%d)",ret); data |= (u32)(reverse_8bits(ret) & 0xff) << 24; return sprintf(buf, "0x%08x\n", data); //return 32bits data @@ -1197,6 +1197,7 @@ static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) regaddr, I2C_SMBUS_BYTE_DATA, &data); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) { struct swpld_mux *mux = data; @@ -1272,7 +1273,86 @@ static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) } return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); } +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct swpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld_mux_val=0; + + if ( mux->data.base_nr == BUS3_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = TEMP_FAN_VAL; + break; + case 1: + swpld_mux_val = FAN_EEPROM1_VAL; + break; + case 2: + swpld_mux_val = FAN_EEPROM2_VAL; + break; + case 3: + swpld_mux_val = FAN_EEPROM3_VAL; + break; + case 4: + swpld_mux_val = FAN_EEPROM4_VAL; + break; + case 5: + swpld_mux_val = FAN_EEPROM5_VAL; + break; + case 6: + swpld_mux_val = FANIO_CTL_VAL; + break; + case 7: + case 8: + swpld_mux_val = FAN_CTRL_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = PSU1_VAL; + break; + case 1: + swpld_mux_val = PSU2_VAL; + break; + case 2: + swpld_mux_val = HOT_SWAP1_VAL; + break; + case 3: + swpld_mux_val = HOT_SWAP2_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS5_BASE_NUM ){ + if (chan < 9){ + swpld_mux_val = (u8)(chan) + 0x01; + } + else if (8 < chan && chan < 19){ + swpld_mux_val = (u8)(chan - 9) + 0x10; + } + else if (18 < chan && chan < 29){ + swpld_mux_val = (u8)(chan - 19) + 0x20; + } + else if (28 < chan && chan < 39){ + swpld_mux_val = (u8)(chan - 29) + 0x30; + } + else{ + swpld_mux_val = 0x00; + } + } + else + { + swpld_mux_val = 0x00; + } + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) static int __init swpld_mux_probe(struct platform_device *pdev) { struct swpld_mux *mux; @@ -1351,8 +1431,89 @@ static int __init swpld_mux_probe(struct platform_device *pdev) return ret; } +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, + swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + + return ret; +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) static int __exit swpld_mux_remove(struct platform_device *pdev) { int i; @@ -1398,6 +1559,18 @@ static int __exit swpld_mux_remove(struct platform_device *pdev) return 0; } +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent=muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} +#endif static struct platform_driver swpld_mux_driver = { .probe = swpld_mux_probe, @@ -1410,9 +1583,9 @@ static struct platform_driver swpld_mux_driver = { /*---------------- MUX - end ------------- */ /*---------------- module initialization ------------- */ -static void __init delta_ag9032v1_platform_init(void) +static int __init delta_ag9032v1_platform_init(void) { - struct i2c_client *client; +// struct i2c_client *client; struct i2c_adapter *adapter; struct cpld_platform_data *cpld_pdata; struct swpld_mux_platform_data *swpld_pdata; @@ -1491,7 +1664,7 @@ static void __init delta_ag9032v1_platform_init(void) for (; i >= 0; i--) { platform_device_unregister(&ag9032v1_swpld_mux[i]); } - platform_driver_unregister(&ag9032v1_cpld); + platform_driver_unregister((struct platform_driver *) &ag9032v1_cpld); error_ag9032v1_cpld: platform_driver_unregister(&i2c_device_driver); error_i2c_device_driver: diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c index e47813af3e09..7d9350bc55bd 100644 --- a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c @@ -24,8 +24,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include +#include #include #include #include @@ -43,6 +43,7 @@ u8 psu_member_data = 0x00; + /* Address scanned */ static const unsigned short normal_i2c[] = { 0x58, I2C_CLIENT_END }; @@ -419,7 +420,7 @@ static SENSOR_DEVICE_ATTR(temp1_input, \ S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); static SENSOR_DEVICE_ATTR(fan1_target, \ S_IRUGO, for_fan_target, NULL, PSU_FAN1_FAULT); -static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUGO | S_IRUGO, \ +static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUSR | S_IRUGO, \ for_linear_data, set_fan_duty_cycle_input, PSU_FAN1_DUTY_CYCLE); static SENSOR_DEVICE_ATTR(fan1_input, \ S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); @@ -427,7 +428,7 @@ static SENSOR_DEVICE_ATTR(psu_mfr_model, \ S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); -static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUGO | S_IRUGO, \ +static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUSR | S_IRUGO, \ for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); static struct attribute *dps_800ab_16_d_attributes[] = { diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/control b/platform/broadcom/sonic-platform-modules-delta/debian/control index 1928e9a767eb..e2b9db283af5 100644 --- a/platform/broadcom/sonic-platform-modules-delta/debian/control +++ b/platform/broadcom/sonic-platform-modules-delta/debian/control @@ -7,5 +7,5 @@ Standards-Version: 3.9.3 Package: platform-modules-ag9032v1 Architecture: amd64 -Depends: linux-image-3.16.0-5-amd64 +Depends: linux-image-4.9.0-5-amd64 Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install index 40f7e56d832d..beca4f51b1f8 100644 --- a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install @@ -1,3 +1,4 @@ ag9032v1/scripts/ag9032v1_platform_init.sh usr/local/bin ag9032v1/scripts/led_status.sh usr/local/bin ag9032v1/cfg/ag9032v1-modules.conf etc/modules-load.d +systemd/platform-modules-ag9032v1.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/rules b/platform/broadcom/sonic-platform-modules-delta/debian/rules index ae590626c817..58a3597e7a44 100755 --- a/platform/broadcom/sonic-platform-modules-delta/debian/rules +++ b/platform/broadcom/sonic-platform-modules-delta/debian/rules @@ -8,7 +8,7 @@ MOD_SRC_DIR:= $(shell pwd) MODULE_DIRS:= ag9032v1 %: - dh $@ + dh $@ --with=systemd override_dh_auto_build: (for mod in $(MODULE_DIRS); do \ diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service new file mode 100644 index 000000000000..bfa0fd296f59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta ag9032v1 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag9032v1 start +ExecStop=-/etc/init.d/platform-modules-ag9032v1 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target