[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHp75VdXDcTfNL9QRQ5XE-zVLHacfMKHUxhse3=dAfJbOJdObQ@mail.gmail.com>
Date: Mon, 15 Mar 2021 12:31:11 +0200
From: Andy Shevchenko <andy.shevchenko@...il.com>
To: Henning Schild <henning.schild@...mens.com>
Cc: Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
Linux LED Subsystem <linux-leds@...r.kernel.org>,
Platform Driver <platform-driver-x86@...r.kernel.org>,
linux-watchdog@...r.kernel.org,
Srikanth Krishnakar <skrishnakar@...il.com>,
Jan Kiszka <jan.kiszka@...mens.com>,
Gerd Haeussler <gerd.haeussler.ext@...mens.com>,
Guenter Roeck <linux@...ck-us.net>,
Wim Van Sebroeck <wim@...ux-watchdog.org>,
Mark Gross <mgross@...ux.intel.com>,
Hans de Goede <hdegoede@...hat.com>,
Pavel Machek <pavel@....cz>
Subject: Re: [PATCH v2 1/4] platform/x86: simatic-ipc: add main driver for
Siemens devices
On Mon, Mar 15, 2021 at 12:02 PM Henning Schild
<henning.schild@...mens.com> wrote:
>
> This mainly implements detection of these devices and will allow
> secondary drivers to work on such machines.
>
> The identification is DMI-based with a vendor specific way to tell them
> apart in a reliable way.
>
> Drivers for LEDs and Watchdogs will follow to make use of that platform
> detection.
...
> +static int register_platform_devices(u32 station_id)
> +{
> + u8 ledmode = SIMATIC_IPC_DEVICE_NONE;
> + u8 wdtmode = SIMATIC_IPC_DEVICE_NONE;
> + int i;
> +
> + platform_data.devmode = SIMATIC_IPC_DEVICE_NONE;
> +
> + for (i = 0; i < ARRAY_SIZE(device_modes); i++) {
> + if (device_modes[i].station_id == station_id) {
> + ledmode = device_modes[i].led_mode;
> + wdtmode = device_modes[i].wdt_mode;
> + break;
> + }
> + }
> +
> + if (ledmode != SIMATIC_IPC_DEVICE_NONE) {
> + platform_data.devmode = ledmode;
> + ipc_led_platform_device =
> + platform_device_register_data(NULL,
> + KBUILD_MODNAME "_leds", PLATFORM_DEVID_NONE,
> + &platform_data,
> + sizeof(struct simatic_ipc_platform));
> + if (IS_ERR(ipc_led_platform_device))
> + return PTR_ERR(ipc_led_platform_device);
> +
> + pr_debug("device=%s created\n",
> + ipc_led_platform_device->name);
> + }
> +
> + if (wdtmode != SIMATIC_IPC_DEVICE_NONE) {
> + platform_data.devmode = wdtmode;
> + ipc_wdt_platform_device =
> + platform_device_register_data(NULL,
> + KBUILD_MODNAME "_wdt", PLATFORM_DEVID_NONE,
> + &platform_data,
> + sizeof(struct simatic_ipc_platform));
> + if (IS_ERR(ipc_wdt_platform_device))
> + return PTR_ERR(ipc_wdt_platform_device);
> +
> + pr_debug("device=%s created\n",
> + ipc_wdt_platform_device->name);
> + }
> +
> + if (ledmode == SIMATIC_IPC_DEVICE_NONE &&
> + wdtmode == SIMATIC_IPC_DEVICE_NONE) {
> + pr_warn("unsupported IPC detected, station id=%08x\n",
> + station_id);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
Why not use MFD here?
...
> +/*
> + * Get membase address from PCI, used in leds and wdt modul. Here we read
> + * the bar0. The final address calculation is done in the appropriate modules
> + */
No blank line here.
I would add FIXME or REVISIT here to point out that this should be
deduplicated in the future.
> +u32 simatic_ipc_get_membase0(unsigned int p2sb)
> +{
> + struct pci_bus *bus;
> + u32 bar0 = 0;
> +
> + /*
> + * The GPIO memory is bar0 of the hidden P2SB device. Unhide the device
No, it's not a GPIO's bar. It's P2SB's one. GPIO resides in that bar somewhere.
> + * to have a quick look at it, before we hide it again.
> + * Also grab the pci rescan lock so that device does not get discovered
> + * and remapped while it is visible.
> + * This code is inspired by drivers/mfd/lpc_ich.c
> + */
> + bus = pci_find_bus(0, 0);
> + pci_lock_rescan_remove();
> + pci_bus_write_config_byte(bus, p2sb, 0xE1, 0x0);
> + pci_bus_read_config_dword(bus, p2sb, PCI_BASE_ADDRESS_0, &bar0);
> +
> + bar0 &= ~0xf;
> + pci_bus_write_config_byte(bus, p2sb, 0xE1, 0x1);
> + pci_unlock_rescan_remove();
> +
> + return bar0;
> +}
> +EXPORT_SYMBOL(simatic_ipc_get_membase0);
...
> +static inline u32 simatic_ipc_get_station_id(u8 *data, int max_len)
> +{
> + u32 station_id = SIMATIC_IPC_INVALID_STATION_ID;
> + int i;
Reversed xmas tree order, please.
> + struct {
> + u8 type; /* type (0xff = binary) */
> + u8 len; /* len of data entry */
> + u8 reserved[3];
> + u32 station_id; /* station id (LE) */
> + } __packed
> + *data_entry = (void *)data + sizeof(struct dmi_header);
Can be one line.
> + /* find 4th entry in OEM data */
> + for (i = 0; i < 3; i++)
3 is magic!
> + data_entry = (void *)((u8 *)(data_entry) + data_entry->len);
> +
> + /* decode station id */
> + if (data_entry && (u8 *)data_entry < data + max_len &&
> + data_entry->type == 0xff && data_entry->len == 9)
> + station_id = le32_to_cpu(data_entry->station_id);
> +
> + return station_id;
> +}
--
With Best Regards,
Andy Shevchenko
Powered by blists - more mailing lists