// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved. * Author: Zhichang Yuan <[email protected]> * Author: Zou Rongrong <[email protected]> * Author: John Garry <[email protected]> */ #include <linux/acpi.h> #include <linux/console.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/logic_pio.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/serial_8250.h> #include <linux/slab.h> #define DRV_NAME … /* * Setting this bit means each IO operation will target a different port * address; 0 means repeated IO operations will use the same port, * such as BT. */ #define FG_INCRADDR_LPC … struct lpc_cycle_para { … }; struct hisi_lpc_dev { … }; /* The max IO cycle counts supported is four per operation at maximum */ #define LPC_MAX_DWIDTH … #define LPC_REG_STARTUP_SIGNAL … #define LPC_REG_STARTUP_SIGNAL_START … #define LPC_REG_OP_STATUS … #define LPC_REG_OP_STATUS_IDLE … #define LPC_REG_OP_STATUS_FINISHED … #define LPC_REG_OP_LEN … #define LPC_REG_CMD … #define LPC_REG_CMD_OP … #define LPC_REG_CMD_SAMEADDR … #define LPC_REG_ADDR … #define LPC_REG_WDATA … #define LPC_REG_RDATA … /* The minimal nanosecond interval for each query on LPC cycle status */ #define LPC_NSEC_PERWAIT … /* * The maximum waiting time is about 128us. It is specific for stream I/O, * such as ins. * * The fastest IO cycle time is about 390ns, but the worst case will wait * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum burst * cycles is 16. So, the maximum waiting time is about 128us under worst * case. * * Choose 1300 as the maximum. */ #define LPC_MAX_WAITCNT … /* About 10us. This is specific for single IO operations, such as inb */ #define LPC_PEROP_WAITCNT … static int wait_lpc_idle(void __iomem *mbase, unsigned int waitcnt) { … } /* * hisi_lpc_target_in - trigger a series of LPC cycles for read operation * @lpcdev: pointer to hisi lpc device * @para: some parameters used to control the lpc I/O operations * @addr: the lpc I/O target port address * @buf: where the read back data is stored * @opcnt: how many I/O operations required, i.e. data width * * Returns 0 on success, non-zero on fail. */ static int hisi_lpc_target_in(struct hisi_lpc_dev *lpcdev, struct lpc_cycle_para *para, unsigned long addr, unsigned char *buf, unsigned long opcnt) { … } /* * hisi_lpc_target_out - trigger a series of LPC cycles for write operation * @lpcdev: pointer to hisi lpc device * @para: some parameters used to control the lpc I/O operations * @addr: the lpc I/O target port address * @buf: where the data to be written is stored * @opcnt: how many I/O operations required, i.e. data width * * Returns 0 on success, non-zero on fail. */ static int hisi_lpc_target_out(struct hisi_lpc_dev *lpcdev, struct lpc_cycle_para *para, unsigned long addr, const unsigned char *buf, unsigned long opcnt) { … } static unsigned long hisi_lpc_pio_to_addr(struct hisi_lpc_dev *lpcdev, unsigned long pio) { … } /* * hisi_lpc_comm_in - input the data in a single operation * @hostdata: pointer to the device information relevant to LPC controller * @pio: the target I/O port address * @dwidth: the data length required to read from the target I/O port * * When success, data is returned. Otherwise, ~0 is returned. */ static u32 hisi_lpc_comm_in(void *hostdata, unsigned long pio, size_t dwidth) { … } /* * hisi_lpc_comm_out - output the data in a single operation * @hostdata: pointer to the device information relevant to LPC controller * @pio: the target I/O port address * @val: a value to be output from caller, maximum is four bytes * @dwidth: the data width required writing to the target I/O port * * This function corresponds to out(b,w,l) only. */ static void hisi_lpc_comm_out(void *hostdata, unsigned long pio, u32 val, size_t dwidth) { … } /* * hisi_lpc_comm_ins - input the data in the buffer in multiple operations * @hostdata: pointer to the device information relevant to LPC controller * @pio: the target I/O port address * @buffer: a buffer where read/input data bytes are stored * @dwidth: the data width required writing to the target I/O port * @count: how many data units whose length is dwidth will be read * * When success, the data read back is stored in buffer pointed by buffer. * Returns 0 on success, -errno otherwise. */ static u32 hisi_lpc_comm_ins(void *hostdata, unsigned long pio, void *buffer, size_t dwidth, unsigned int count) { … } /* * hisi_lpc_comm_outs - output the data in the buffer in multiple operations * @hostdata: pointer to the device information relevant to LPC controller * @pio: the target I/O port address * @buffer: a buffer where write/output data bytes are stored * @dwidth: the data width required writing to the target I/O port * @count: how many data units whose length is dwidth will be written */ static void hisi_lpc_comm_outs(void *hostdata, unsigned long pio, const void *buffer, size_t dwidth, unsigned int count) { … } static const struct logic_pio_host_ops hisi_lpc_ops = …; #ifdef CONFIG_ACPI static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, struct acpi_device *host, struct resource *res) { … } /* * Released firmware describes the IO port max address as 0x3fff, which is * the max host bus address. Fixup to a proper range. This will probably * never be fixed in firmware. */ static void hisi_lpc_acpi_fixup_child_resource(struct device *hostdev, struct resource *r) { … } /* * hisi_lpc_acpi_set_io_res - set the resources for a child * @adev: ACPI companion of the device node to be updated the I/O resource * @hostdev: the device node associated with host controller * @res: double pointer to be set to the address of translated resources * @num_res: pointer to variable to hold the number of translated resources * * Returns 0 when successful, and a negative value for failure. * * For a given host controller, each child device will have an associated * host-relative address resource. This function will return the translated * logical PIO addresses for each child devices resources. */ static int hisi_lpc_acpi_set_io_res(struct acpi_device *adev, struct device *hostdev, const struct resource **res, int *num_res) { … } static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused) { … } static int hisi_lpc_acpi_clear_enumerated(struct acpi_device *adev, void *not_used) { … } struct hisi_lpc_acpi_cell { … }; static void hisi_lpc_acpi_remove(struct device *hostdev) { … } static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data) { … } /* * hisi_lpc_acpi_probe - probe children for ACPI FW * @hostdev: LPC host device pointer * * Returns 0 when successful, and a negative value for failure. * * Create a platform device per child, fixing up the resources * from bus addresses to Logical PIO addresses. * */ static int hisi_lpc_acpi_probe(struct device *hostdev) { … } #else static int hisi_lpc_acpi_probe(struct device *dev) { return -ENODEV; } static void hisi_lpc_acpi_remove(struct device *hostdev) { } #endif // CONFIG_ACPI /* * hisi_lpc_probe - the probe callback function for hisi lpc host, * will finish all the initialization. * @pdev: the platform device corresponding to hisi lpc host * * Returns 0 on success, non-zero on fail. */ static int hisi_lpc_probe(struct platform_device *pdev) { … } static void hisi_lpc_remove(struct platform_device *pdev) { … } static const struct of_device_id hisi_lpc_of_match[] = …; static const struct acpi_device_id hisi_lpc_acpi_match[] = …; static struct platform_driver hisi_lpc_driver = …; builtin_platform_driver(…) …;