Message ID | a4cfdeed1a91a7a12c7ebe56bed2ba94991c4065.1735550269.git.zhoubinbin@loongson.cn (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | LoongArch: Add Loongson-2K0500 BMC support | expand |
Hi Binbin, kernel test robot noticed the following build warnings: [auto build test WARNING on linus/master] [also build test WARNING on v6.13-rc5] [cannot apply to cminyard-ipmi/for-next lee-mfd/for-mfd-next lee-mfd/for-mfd-fixes next-20241220] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Binbin-Zhou/mfd-ls2kbmc-Introduce-Loongson-2K-BMC-MFD-Core-driver/20241230-174205 base: linus/master patch link: https://lore.kernel.org/r/a4cfdeed1a91a7a12c7ebe56bed2ba94991c4065.1735550269.git.zhoubinbin%40loongson.cn patch subject: [PATCH v1 2/4] ipmi: Add Loongson-2K BMC support config: loongarch-randconfig-r123-20241231 (https://download.01.org/0day-ci/archive/20241231/202412311950.Ij7v1vKv-lkp@intel.com/config) compiler: loongarch64-linux-gcc (GCC) 14.2.0 reproduce: (https://download.01.org/0day-ci/archive/20241231/202412311950.Ij7v1vKv-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412311950.Ij7v1vKv-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/char/ipmi/ipmi_si_ls2k.c:110:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ls2k_kcs_data *ik @@ got void [noderef] __iomem *const addr @@ drivers/char/ipmi/ipmi_si_ls2k.c:110:38: sparse: expected struct ls2k_kcs_data *ik drivers/char/ipmi/ipmi_si_ls2k.c:110:38: sparse: got void [noderef] __iomem *const addr drivers/char/ipmi/ipmi_si_ls2k.c:168:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ls2k_kcs_data *ik @@ got void [noderef] __iomem *const addr @@ drivers/char/ipmi/ipmi_si_ls2k.c:168:38: sparse: expected struct ls2k_kcs_data *ik drivers/char/ipmi/ipmi_si_ls2k.c:168:38: sparse: got void [noderef] __iomem *const addr >> drivers/char/ipmi/ipmi_si_ls2k.c:226:24: sparse: sparse: symbol 'ipmi_ls2k_platform_driver' was not declared. Should it be static? vim +110 drivers/char/ipmi/ipmi_si_ls2k.c 106 107 static unsigned char ls2k_mem_inb(const struct si_sm_io *io, 108 unsigned int offset) 109 { > 110 struct ls2k_kcs_data *ik = io->addr; 111 int inb = 0; 112 113 if (ik->version == 0) 114 inb = intf_sim_inb_v0(ik, offset); 115 else if (ik->version == 1) 116 inb = intf_sim_inb_v1(ik, offset); 117 118 return inb; 119 } 120 121 static void intf_sim_outb_v0(struct ls2k_kcs_data *ik, unsigned int offset, 122 unsigned char val) 123 { 124 if (ls2k_get_ibf(ik)) 125 return; 126 127 switch (offset & BIT(0)) { 128 case 0: 129 ik->reg.data_in = val; 130 ik->reg.status &= ~LS2K_KCS_STS_CMD; 131 break; 132 133 case 1: 134 ik->reg.cmd = val; 135 ik->reg.status |= LS2K_KCS_STS_CMD; 136 break; 137 } 138 139 ls2k_set_ibf(ik, 1); 140 ik->write_req++; 141 } 142 143 static void intf_sim_outb_v1(struct ls2k_kcs_data *ik, unsigned int offset, 144 unsigned char val) 145 { 146 if (ik->fifo.ibfh != ik->fifo.ibft) 147 return; 148 149 switch (offset & BIT(0)) { 150 case 0: 151 ik->reg.data_in = val; 152 ik->cmd_data = 0; 153 break; 154 155 case 1: 156 ik->reg.cmd = val; 157 ik->cmd_data = 1; 158 break; 159 } 160 161 ik->fifo.ibfh = !ik->fifo.ibft; 162 ik->write_req++; 163 } 164 165 static void ls2k_mem_outb(const struct si_sm_io *io, unsigned int offset, 166 unsigned char val) 167 { 168 struct ls2k_kcs_data *ik = io->addr; 169 170 if (ik->version == 0) 171 intf_sim_outb_v0(ik, offset, val); 172 else if (ik->version == 1) 173 intf_sim_outb_v1(ik, offset, val); 174 } 175 176 static void ls2k_mem_cleanup(struct si_sm_io *io) 177 { 178 if (io->addr) 179 iounmap(io->addr); 180 } 181 182 static int ipmi_ls2k_sim_setup(struct si_sm_io *io) 183 { 184 io->addr = ioremap(io->addr_data, io->regspacing); 185 if (!io->addr) 186 return -EIO; 187 188 io->inputb = ls2k_mem_inb; 189 io->outputb = ls2k_mem_outb; 190 io->io_cleanup = ls2k_mem_cleanup; 191 192 return 0; 193 } 194 195 static int ipmi_ls2k_probe(struct platform_device *pdev) 196 { 197 struct si_sm_io io; 198 199 dev_info(&pdev->dev, "probing via ls2k platform"); 200 memset(&io, 0, sizeof(io)); 201 202 io.addr_source = SI_PLATFORM; 203 io.si_type = SI_KCS; 204 io.addr_space = IPMI_MEM_ADDR_SPACE; 205 io.io_setup = ipmi_ls2k_sim_setup; 206 io.addr_data = pdev->resource[0].start; 207 io.regspacing = pdev->resource[0].end - pdev->resource[0].start + 1; 208 io.regsize = DEFAULT_REGSIZE; 209 io.regshift = 0; 210 io.dev = &pdev->dev; 211 io.irq = 0; 212 if (io.irq) 213 io.irq_setup = ipmi_std_irq_setup; 214 215 dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n", 216 &pdev->resource[0], io.regsize, io.regspacing, io.irq); 217 218 return ipmi_si_add_smi(&io); 219 } 220 221 static void ipmi_ls2k_remove(struct platform_device *pdev) 222 { 223 ipmi_si_remove_by_dev(&pdev->dev); 224 } 225 > 226 struct platform_driver ipmi_ls2k_platform_driver = { 227 .driver = { 228 .name = "ls2k-ipmi-si", 229 }, 230 .probe = ipmi_ls2k_probe, 231 .remove = ipmi_ls2k_remove, 232 }; 233
Hi Binbin, kernel test robot noticed the following build warnings: [auto build test WARNING on linus/master] [also build test WARNING on v6.13-rc5] [cannot apply to cminyard-ipmi/for-next lee-mfd/for-mfd-next lee-mfd/for-mfd-fixes next-20241220] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Binbin-Zhou/mfd-ls2kbmc-Introduce-Loongson-2K-BMC-MFD-Core-driver/20241230-174205 base: linus/master patch link: https://lore.kernel.org/r/a4cfdeed1a91a7a12c7ebe56bed2ba94991c4065.1735550269.git.zhoubinbin%40loongson.cn patch subject: [PATCH v1 2/4] ipmi: Add Loongson-2K BMC support config: loongarch-randconfig-r123-20241231 (https://download.01.org/0day-ci/archive/20250103/202501031235.JEXCZscQ-lkp@intel.com/config) compiler: loongarch64-linux-gcc (GCC) 14.2.0 reproduce: (https://download.01.org/0day-ci/archive/20250103/202501031235.JEXCZscQ-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202501031235.JEXCZscQ-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/char/ipmi/ipmi_si_ls2k.c:110:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ls2k_kcs_data *ik @@ got void [noderef] __iomem *const addr @@ drivers/char/ipmi/ipmi_si_ls2k.c:110:38: sparse: expected struct ls2k_kcs_data *ik drivers/char/ipmi/ipmi_si_ls2k.c:110:38: sparse: got void [noderef] __iomem *const addr drivers/char/ipmi/ipmi_si_ls2k.c:168:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct ls2k_kcs_data *ik @@ got void [noderef] __iomem *const addr @@ drivers/char/ipmi/ipmi_si_ls2k.c:168:38: sparse: expected struct ls2k_kcs_data *ik drivers/char/ipmi/ipmi_si_ls2k.c:168:38: sparse: got void [noderef] __iomem *const addr >> drivers/char/ipmi/ipmi_si_ls2k.c:226:24: sparse: sparse: symbol 'ipmi_ls2k_platform_driver' was not declared. Should it be static? vim +110 drivers/char/ipmi/ipmi_si_ls2k.c 106 107 static unsigned char ls2k_mem_inb(const struct si_sm_io *io, 108 unsigned int offset) 109 { > 110 struct ls2k_kcs_data *ik = io->addr; 111 int inb = 0; 112 113 if (ik->version == 0) 114 inb = intf_sim_inb_v0(ik, offset); 115 else if (ik->version == 1) 116 inb = intf_sim_inb_v1(ik, offset); 117 118 return inb; 119 } 120 121 static void intf_sim_outb_v0(struct ls2k_kcs_data *ik, unsigned int offset, 122 unsigned char val) 123 { 124 if (ls2k_get_ibf(ik)) 125 return; 126 127 switch (offset & BIT(0)) { 128 case 0: 129 ik->reg.data_in = val; 130 ik->reg.status &= ~LS2K_KCS_STS_CMD; 131 break; 132 133 case 1: 134 ik->reg.cmd = val; 135 ik->reg.status |= LS2K_KCS_STS_CMD; 136 break; 137 } 138 139 ls2k_set_ibf(ik, 1); 140 ik->write_req++; 141 } 142 143 static void intf_sim_outb_v1(struct ls2k_kcs_data *ik, unsigned int offset, 144 unsigned char val) 145 { 146 if (ik->fifo.ibfh != ik->fifo.ibft) 147 return; 148 149 switch (offset & BIT(0)) { 150 case 0: 151 ik->reg.data_in = val; 152 ik->cmd_data = 0; 153 break; 154 155 case 1: 156 ik->reg.cmd = val; 157 ik->cmd_data = 1; 158 break; 159 } 160 161 ik->fifo.ibfh = !ik->fifo.ibft; 162 ik->write_req++; 163 } 164 165 static void ls2k_mem_outb(const struct si_sm_io *io, unsigned int offset, 166 unsigned char val) 167 { 168 struct ls2k_kcs_data *ik = io->addr; 169 170 if (ik->version == 0) 171 intf_sim_outb_v0(ik, offset, val); 172 else if (ik->version == 1) 173 intf_sim_outb_v1(ik, offset, val); 174 } 175 176 static void ls2k_mem_cleanup(struct si_sm_io *io) 177 { 178 if (io->addr) 179 iounmap(io->addr); 180 } 181 182 static int ipmi_ls2k_sim_setup(struct si_sm_io *io) 183 { 184 io->addr = ioremap(io->addr_data, io->regspacing); 185 if (!io->addr) 186 return -EIO; 187 188 io->inputb = ls2k_mem_inb; 189 io->outputb = ls2k_mem_outb; 190 io->io_cleanup = ls2k_mem_cleanup; 191 192 return 0; 193 } 194 195 static int ipmi_ls2k_probe(struct platform_device *pdev) 196 { 197 struct si_sm_io io; 198 199 dev_info(&pdev->dev, "probing via ls2k platform"); 200 memset(&io, 0, sizeof(io)); 201 202 io.addr_source = SI_PLATFORM; 203 io.si_type = SI_KCS; 204 io.addr_space = IPMI_MEM_ADDR_SPACE; 205 io.io_setup = ipmi_ls2k_sim_setup; 206 io.addr_data = pdev->resource[0].start; 207 io.regspacing = pdev->resource[0].end - pdev->resource[0].start + 1; 208 io.regsize = DEFAULT_REGSIZE; 209 io.regshift = 0; 210 io.dev = &pdev->dev; 211 io.irq = 0; 212 if (io.irq) 213 io.irq_setup = ipmi_std_irq_setup; 214 215 dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n", 216 &pdev->resource[0], io.regsize, io.regspacing, io.irq); 217 218 return ipmi_si_add_smi(&io); 219 } 220 221 static void ipmi_ls2k_remove(struct platform_device *pdev) 222 { 223 ipmi_si_remove_by_dev(&pdev->dev); 224 } 225 > 226 struct platform_driver ipmi_ls2k_platform_driver = { 227 .driver = { 228 .name = "ls2k-ipmi-si", 229 }, 230 .probe = ipmi_ls2k_probe, 231 .remove = ipmi_ls2k_remove, 232 }; 233
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index e0944547c9d0..614be45863b4 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -7,6 +7,7 @@ ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o \ ipmi_si_hotmod.o ipmi_si_hardcode.o ipmi_si_platform.o \ ipmi_si_mem_io.o ipmi_si-$(CONFIG_HAS_IOPORT) += ipmi_si_port_io.o +ipmi_si-$(CONFIG_LOONGARCH) += ipmi_si_ls2k.o ipmi_si-$(CONFIG_PCI) += ipmi_si_pci.o ipmi_si-$(CONFIG_PARISC) += ipmi_si_parisc.o diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h index a7ead2a4c753..0a4af352a42c 100644 --- a/drivers/char/ipmi/ipmi_si.h +++ b/drivers/char/ipmi/ipmi_si.h @@ -101,6 +101,14 @@ static inline void ipmi_si_parisc_init(void) { } static inline void ipmi_si_parisc_shutdown(void) { } #endif +#ifdef CONFIG_LOONGARCH +void ipmi_si_ls2k_init(void); +void ipmi_si_ls2k_shutdown(void); +#else +static inline void ipmi_si_ls2k_init(void) { } +static inline void ipmi_si_ls2k_shutdown(void) { } +#endif + int ipmi_si_port_setup(struct si_sm_io *io); int ipmi_si_mem_setup(struct si_sm_io *io); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index eea23a3b966e..7227bc61be79 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2108,6 +2108,7 @@ static int __init init_ipmi_si(void) ipmi_si_pci_init(); ipmi_si_parisc_init(); + ipmi_si_ls2k_init(); /* We prefer devices with interrupts, but in the case of a machine with multiple BMCs we assume that there will be several instances @@ -2292,6 +2293,8 @@ static void cleanup_ipmi_si(void) ipmi_si_platform_shutdown(); + ipmi_si_ls2k_shutdown(); + mutex_lock(&smi_infos_lock); list_for_each_entry_safe(e, tmp_e, &smi_infos, link) cleanup_one_si(e); diff --git a/drivers/char/ipmi/ipmi_si_ls2k.c b/drivers/char/ipmi/ipmi_si_ls2k.c new file mode 100644 index 000000000000..cb31bb989fca --- /dev/null +++ b/drivers/char/ipmi/ipmi_si_ls2k.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for Loongson-2K BMC IPMI + * + * Copyright (C) 2024 Loongson Technology Corporation Limited. + * + * Originally written by Chong Qiao <qiaochong@loongson.cn> + * Rewritten for mainline by Binbin Zhou <zhoubinbin@loongson.cn> + */ + +#include <linux/ioport.h> +#include <linux/module.h> +#include <linux/types.h> + +#include "ipmi_si.h" + +#define LS2K_KCS_STS_OBF BIT(0) +#define LS2K_KCS_STS_IBF BIT(1) +#define LS2K_KCS_STS_SMS_ATN BIT(2) +#define LS2K_KCS_STS_CMD BIT(3) + +#define LS2K_KCS_DATA_MASK (LS2K_KCS_STS_OBF | LS2K_KCS_STS_IBF | LS2K_KCS_STS_CMD) + +/* Read and write fifo pointers for data consistency. */ +struct ls2k_fifo_flag { + u8 ibfh; + u8 ibft; + u8 obfh; + u8 obft; +}; + +struct ls2k_kcs_reg { + u8 status; + u8 data_out; + s16 data_in; + s16 cmd; +}; + +struct ls2k_kcs_data { + struct ls2k_fifo_flag fifo; + struct ls2k_kcs_reg reg; + u8 cmd_data; + u8 version; + u32 write_req; + u32 write_ack; + u32 reserved[2]; +}; + +static void ls2k_set_obf(struct ls2k_kcs_data *ik, u8 sts) +{ + ik->reg.status = (ik->reg.status & ~LS2K_KCS_STS_OBF) | (sts & BIT(0)); +} + +static void ls2k_set_ibf(struct ls2k_kcs_data *ik, u8 sts) +{ + ik->reg.status = (ik->reg.status & ~LS2K_KCS_STS_IBF) | ((sts & BIT(0)) << 1); +} + +static u8 ls2k_get_ibf(struct ls2k_kcs_data *ik) +{ + return (ik->reg.status >> 1) & BIT(0); +} + +static unsigned char intf_sim_inb_v0(struct ls2k_kcs_data *ik, + unsigned int offset) +{ + u32 inb = 0; + + switch (offset & BIT(0)) { + case 0: + inb = ik->reg.data_out; + ls2k_set_obf(ik, 0); + break; + case 1: + inb = ik->reg.status; + break; + } + + return inb; +} + +static unsigned char intf_sim_inb_v1(struct ls2k_kcs_data *ik, + unsigned int offset) +{ + u32 inb = 0; + int cmd; + bool obf, ibf; + + obf = ik->fifo.obfh != ik->fifo.obft; + ibf = ik->fifo.ibfh != ik->fifo.ibft; + cmd = ik->cmd_data; + + switch (offset & BIT(0)) { + case 0: + inb = ik->reg.data_out; + ik->fifo.obft = ik->fifo.obfh; + break; + case 1: + inb = ik->reg.status & ~LS2K_KCS_DATA_MASK; + inb |= obf | (ibf << 1) | (cmd << 3); + break; + } + + return inb; +} + +static unsigned char ls2k_mem_inb(const struct si_sm_io *io, + unsigned int offset) +{ + struct ls2k_kcs_data *ik = io->addr; + int inb = 0; + + if (ik->version == 0) + inb = intf_sim_inb_v0(ik, offset); + else if (ik->version == 1) + inb = intf_sim_inb_v1(ik, offset); + + return inb; +} + +static void intf_sim_outb_v0(struct ls2k_kcs_data *ik, unsigned int offset, + unsigned char val) +{ + if (ls2k_get_ibf(ik)) + return; + + switch (offset & BIT(0)) { + case 0: + ik->reg.data_in = val; + ik->reg.status &= ~LS2K_KCS_STS_CMD; + break; + + case 1: + ik->reg.cmd = val; + ik->reg.status |= LS2K_KCS_STS_CMD; + break; + } + + ls2k_set_ibf(ik, 1); + ik->write_req++; +} + +static void intf_sim_outb_v1(struct ls2k_kcs_data *ik, unsigned int offset, + unsigned char val) +{ + if (ik->fifo.ibfh != ik->fifo.ibft) + return; + + switch (offset & BIT(0)) { + case 0: + ik->reg.data_in = val; + ik->cmd_data = 0; + break; + + case 1: + ik->reg.cmd = val; + ik->cmd_data = 1; + break; + } + + ik->fifo.ibfh = !ik->fifo.ibft; + ik->write_req++; +} + +static void ls2k_mem_outb(const struct si_sm_io *io, unsigned int offset, + unsigned char val) +{ + struct ls2k_kcs_data *ik = io->addr; + + if (ik->version == 0) + intf_sim_outb_v0(ik, offset, val); + else if (ik->version == 1) + intf_sim_outb_v1(ik, offset, val); +} + +static void ls2k_mem_cleanup(struct si_sm_io *io) +{ + if (io->addr) + iounmap(io->addr); +} + +static int ipmi_ls2k_sim_setup(struct si_sm_io *io) +{ + io->addr = ioremap(io->addr_data, io->regspacing); + if (!io->addr) + return -EIO; + + io->inputb = ls2k_mem_inb; + io->outputb = ls2k_mem_outb; + io->io_cleanup = ls2k_mem_cleanup; + + return 0; +} + +static int ipmi_ls2k_probe(struct platform_device *pdev) +{ + struct si_sm_io io; + + dev_info(&pdev->dev, "probing via ls2k platform"); + memset(&io, 0, sizeof(io)); + + io.addr_source = SI_PLATFORM; + io.si_type = SI_KCS; + io.addr_space = IPMI_MEM_ADDR_SPACE; + io.io_setup = ipmi_ls2k_sim_setup; + io.addr_data = pdev->resource[0].start; + io.regspacing = pdev->resource[0].end - pdev->resource[0].start + 1; + io.regsize = DEFAULT_REGSIZE; + io.regshift = 0; + io.dev = &pdev->dev; + io.irq = 0; + if (io.irq) + io.irq_setup = ipmi_std_irq_setup; + + dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n", + &pdev->resource[0], io.regsize, io.regspacing, io.irq); + + return ipmi_si_add_smi(&io); +} + +static void ipmi_ls2k_remove(struct platform_device *pdev) +{ + ipmi_si_remove_by_dev(&pdev->dev); +} + +struct platform_driver ipmi_ls2k_platform_driver = { + .driver = { + .name = "ls2k-ipmi-si", + }, + .probe = ipmi_ls2k_probe, + .remove = ipmi_ls2k_remove, +}; + +static bool platform_registered; +void ipmi_si_ls2k_init(void) +{ + int rv; + + rv = platform_driver_register(&ipmi_ls2k_platform_driver); + if (rv) + pr_err("Unable to register driver: %d\n", rv); + else + platform_registered = true; +} + +void ipmi_si_ls2k_shutdown(void) +{ + if (platform_registered) + platform_driver_unregister(&ipmi_ls2k_platform_driver); +}