irq-mbigen.c (76e1f77f9c26ec96ce58f46cc74ad07c731bd7ba) | irq-mbigen.c (f907c515ffb06e6fd5e74397badd674f3c233418) |
---|---|
1/* 2 * Copyright (C) 2015 Hisilicon Limited, All Rights Reserved. 3 * Author: Jun Ma <majun258@huawei.com> 4 * Author: Yun Wu <wuyun.wu@huawei.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 | 1/* 2 * Copyright (C) 2015 Hisilicon Limited, All Rights Reserved. 3 * Author: Jun Ma <majun258@huawei.com> 4 * Author: Yun Wu <wuyun.wu@huawei.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 |
19#include <linux/acpi.h> |
|
19#include <linux/interrupt.h> 20#include <linux/irqchip.h> 21#include <linux/module.h> 22#include <linux/msi.h> 23#include <linux/of_address.h> 24#include <linux/of_irq.h> 25#include <linux/of_platform.h> 26#include <linux/platform_device.h> --- 148 unchanged lines hidden (view full) --- 175 writel_relaxed(val, base); 176} 177 178static int mbigen_domain_translate(struct irq_domain *d, 179 struct irq_fwspec *fwspec, 180 unsigned long *hwirq, 181 unsigned int *type) 182{ | 20#include <linux/interrupt.h> 21#include <linux/irqchip.h> 22#include <linux/module.h> 23#include <linux/msi.h> 24#include <linux/of_address.h> 25#include <linux/of_irq.h> 26#include <linux/of_platform.h> 27#include <linux/platform_device.h> --- 148 unchanged lines hidden (view full) --- 176 writel_relaxed(val, base); 177} 178 179static int mbigen_domain_translate(struct irq_domain *d, 180 struct irq_fwspec *fwspec, 181 unsigned long *hwirq, 182 unsigned int *type) 183{ |
183 if (is_of_node(fwspec->fwnode)) { | 184 if (is_of_node(fwspec->fwnode) || is_acpi_device_node(fwspec->fwnode)) { |
184 if (fwspec->param_count != 2) 185 return -EINVAL; 186 187 if ((fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) || 188 (fwspec->param[0] < RESERVED_IRQ_PER_MBIGEN_CHIP)) 189 return -EINVAL; 190 else 191 *hwirq = fwspec->param[0]; --- 74 unchanged lines hidden (view full) --- 266 mgn_chip); 267 if (!domain) 268 return -ENOMEM; 269 } 270 271 return 0; 272} 273 | 185 if (fwspec->param_count != 2) 186 return -EINVAL; 187 188 if ((fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) || 189 (fwspec->param[0] < RESERVED_IRQ_PER_MBIGEN_CHIP)) 190 return -EINVAL; 191 else 192 *hwirq = fwspec->param[0]; --- 74 unchanged lines hidden (view full) --- 267 mgn_chip); 268 if (!domain) 269 return -ENOMEM; 270 } 271 272 return 0; 273} 274 |
275#ifdef CONFIG_ACPI 276static int mbigen_acpi_create_domain(struct platform_device *pdev, 277 struct mbigen_device *mgn_chip) 278{ 279 struct irq_domain *domain; 280 u32 num_pins = 0; 281 int ret; 282 283 /* 284 * "num-pins" is the total number of interrupt pins implemented in 285 * this mbigen instance, and mbigen is an interrupt controller 286 * connected to ITS converting wired interrupts into MSI, so we 287 * use "num-pins" to alloc MSI vectors which are needed by client 288 * devices connected to it. 289 * 290 * Here is the DSDT device node used for mbigen in firmware: 291 * Device(MBI0) { 292 * Name(_HID, "HISI0152") 293 * Name(_UID, Zero) 294 * Name(_CRS, ResourceTemplate() { 295 * Memory32Fixed(ReadWrite, 0xa0080000, 0x10000) 296 * }) 297 * 298 * Name(_DSD, Package () { 299 * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 300 * Package () { 301 * Package () {"num-pins", 378} 302 * } 303 * }) 304 * } 305 */ 306 ret = device_property_read_u32(&pdev->dev, "num-pins", &num_pins); 307 if (ret || num_pins == 0) 308 return -EINVAL; 309 310 domain = platform_msi_create_device_domain(&pdev->dev, num_pins, 311 mbigen_write_msg, 312 &mbigen_domain_ops, 313 mgn_chip); 314 if (!domain) 315 return -ENOMEM; 316 317 return 0; 318} 319#else 320static inline int mbigen_acpi_create_domain(struct platform_device *pdev, 321 struct mbigen_device *mgn_chip) 322{ 323 return -ENODEV; 324} 325#endif 326 |
|
274static int mbigen_device_probe(struct platform_device *pdev) 275{ 276 struct mbigen_device *mgn_chip; 277 struct resource *res; 278 int err; 279 280 mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL); 281 if (!mgn_chip) 282 return -ENOMEM; 283 284 mgn_chip->pdev = pdev; 285 286 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 287 mgn_chip->base = devm_ioremap(&pdev->dev, res->start, 288 resource_size(res)); 289 if (IS_ERR(mgn_chip->base)) 290 return PTR_ERR(mgn_chip->base); 291 | 327static int mbigen_device_probe(struct platform_device *pdev) 328{ 329 struct mbigen_device *mgn_chip; 330 struct resource *res; 331 int err; 332 333 mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL); 334 if (!mgn_chip) 335 return -ENOMEM; 336 337 mgn_chip->pdev = pdev; 338 339 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 340 mgn_chip->base = devm_ioremap(&pdev->dev, res->start, 341 resource_size(res)); 342 if (IS_ERR(mgn_chip->base)) 343 return PTR_ERR(mgn_chip->base); 344 |
292 err = mbigen_of_create_domain(pdev, mgn_chip); 293 if (err) | 345 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) 346 err = mbigen_of_create_domain(pdev, mgn_chip); 347 else if (ACPI_COMPANION(&pdev->dev)) 348 err = mbigen_acpi_create_domain(pdev, mgn_chip); 349 else 350 err = -EINVAL; 351 352 if (err) { 353 dev_err(&pdev->dev, "Failed to create mbi-gen@%p irqdomain", 354 mgn_chip->base); |
294 return err; | 355 return err; |
356 } |
|
295 296 platform_set_drvdata(pdev, mgn_chip); 297 return 0; 298} 299 300static const struct of_device_id mbigen_of_match[] = { 301 { .compatible = "hisilicon,mbigen-v2" }, 302 { /* END */ } 303}; 304MODULE_DEVICE_TABLE(of, mbigen_of_match); 305 | 357 358 platform_set_drvdata(pdev, mgn_chip); 359 return 0; 360} 361 362static const struct of_device_id mbigen_of_match[] = { 363 { .compatible = "hisilicon,mbigen-v2" }, 364 { /* END */ } 365}; 366MODULE_DEVICE_TABLE(of, mbigen_of_match); 367 |
368static const struct acpi_device_id mbigen_acpi_match[] = { 369 { "HISI0152", 0 }, 370 {} 371}; 372MODULE_DEVICE_TABLE(acpi, mbigen_acpi_match); 373 |
|
306static struct platform_driver mbigen_platform_driver = { 307 .driver = { 308 .name = "Hisilicon MBIGEN-V2", 309 .of_match_table = mbigen_of_match, | 374static struct platform_driver mbigen_platform_driver = { 375 .driver = { 376 .name = "Hisilicon MBIGEN-V2", 377 .of_match_table = mbigen_of_match, |
378 .acpi_match_table = ACPI_PTR(mbigen_acpi_match), |
|
310 }, 311 .probe = mbigen_device_probe, 312}; 313 314module_platform_driver(mbigen_platform_driver); 315 316MODULE_AUTHOR("Jun Ma <majun258@huawei.com>"); 317MODULE_AUTHOR("Yun Wu <wuyun.wu@huawei.com>"); 318MODULE_LICENSE("GPL"); 319MODULE_DESCRIPTION("Hisilicon MBI Generator driver"); | 379 }, 380 .probe = mbigen_device_probe, 381}; 382 383module_platform_driver(mbigen_platform_driver); 384 385MODULE_AUTHOR("Jun Ma <majun258@huawei.com>"); 386MODULE_AUTHOR("Yun Wu <wuyun.wu@huawei.com>"); 387MODULE_LICENSE("GPL"); 388MODULE_DESCRIPTION("Hisilicon MBI Generator driver"); |