diff options
Diffstat (limited to 'drivers/dma/dw')
-rw-r--r-- | drivers/dma/dw/core.c | 147 | ||||
-rw-r--r-- | drivers/dma/dw/internal.h | 61 | ||||
-rw-r--r-- | drivers/dma/dw/pci.c | 8 | ||||
-rw-r--r-- | drivers/dma/dw/platform.c | 92 | ||||
-rw-r--r-- | drivers/dma/dw/regs.h | 41 |
5 files changed, 154 insertions, 195 deletions
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 1af731b83b3f..244722170410 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -11,7 +11,6 @@ */ #include <linux/bitops.h> -#include <linux/clk.h> #include <linux/delay.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> @@ -37,24 +36,6 @@ * support descriptor writeback. */ -static inline bool is_request_line_unset(struct dw_dma_chan *dwc) -{ - return dwc->request_line == (typeof(dwc->request_line))~0; -} - -static inline void dwc_set_masters(struct dw_dma_chan *dwc) -{ - struct dw_dma *dw = to_dw_dma(dwc->chan.device); - struct dw_dma_slave *dws = dwc->chan.private; - unsigned char mmax = dw->nr_masters - 1; - - if (!is_request_line_unset(dwc)) - return; - - dwc->src_master = min_t(unsigned char, mmax, dwc_get_sms(dws)); - dwc->dst_master = min_t(unsigned char, mmax, dwc_get_dms(dws)); -} - #define DWC_DEFAULT_CTLLO(_chan) ({ \ struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \ struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \ @@ -155,13 +136,11 @@ static void dwc_initialize(struct dw_dma_chan *dwc) */ BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); - cfghi = dws->cfg_hi; - cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; + cfghi |= DWC_CFGH_DST_PER(dws->dst_id); + cfghi |= DWC_CFGH_SRC_PER(dws->src_id); } else { - if (dwc->direction == DMA_MEM_TO_DEV) - cfghi = DWC_CFGH_DST_PER(dwc->request_line); - else if (dwc->direction == DMA_DEV_TO_MEM) - cfghi = DWC_CFGH_SRC_PER(dwc->request_line); + cfghi |= DWC_CFGH_DST_PER(dwc->dst_id); + cfghi |= DWC_CFGH_SRC_PER(dwc->src_id); } channel_writel(dwc, CFG_LO, cfglo); @@ -939,6 +918,26 @@ err_desc_get: return NULL; } +bool dw_dma_filter(struct dma_chan *chan, void *param) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma_slave *dws = param; + + if (!dws || dws->dma_dev != chan->device->dev) + return false; + + /* We have to copy data since dws can be temporary storage */ + + dwc->src_id = dws->src_id; + dwc->dst_id = dws->dst_id; + + dwc->src_master = dws->src_master; + dwc->dst_master = dws->dst_master; + + return true; +} +EXPORT_SYMBOL_GPL(dw_dma_filter); + /* * Fix sconfig's burst size according to dw_dmac. We need to convert them as: * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. @@ -967,10 +966,6 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); dwc->direction = sconfig->direction; - /* Take the request line from slave_id member */ - if (is_request_line_unset(dwc)) - dwc->request_line = sconfig->slave_id; - convert_burst(&dwc->dma_sconfig.src_maxburst); convert_burst(&dwc->dma_sconfig.dst_maxburst); @@ -1099,6 +1094,31 @@ static void dwc_issue_pending(struct dma_chan *chan) spin_unlock_irqrestore(&dwc->lock, flags); } +/*----------------------------------------------------------------------*/ + +static void dw_dma_off(struct dw_dma *dw) +{ + int i; + + dma_writel(dw, CFG, 0); + + channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); + channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask); + channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask); + channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); + + while (dma_readl(dw, CFG) & DW_CFG_DMA_EN) + cpu_relax(); + + for (i = 0; i < dw->dma.chancnt; i++) + dw->chan[i].initialized = false; +} + +static void dw_dma_on(struct dw_dma *dw) +{ + dma_writel(dw, CFG, DW_CFG_DMA_EN); +} + static int dwc_alloc_chan_resources(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); @@ -1123,7 +1143,10 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) * doesn't mean what you think it means), and status writeback. */ - dwc_set_masters(dwc); + /* Enable controller here if needed */ + if (!dw->in_use) + dw_dma_on(dw); + dw->in_use |= dwc->mask; spin_lock_irqsave(&dwc->lock, flags); i = dwc->descs_allocated; @@ -1182,7 +1205,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan) list_splice_init(&dwc->free_list, &list); dwc->descs_allocated = 0; dwc->initialized = false; - dwc->request_line = ~0; /* Disable interrupts */ channel_clear_bit(dw, MASK.XFER, dwc->mask); @@ -1190,6 +1212,11 @@ static void dwc_free_chan_resources(struct dma_chan *chan) spin_unlock_irqrestore(&dwc->lock, flags); + /* Disable controller in case it was a last user */ + dw->in_use &= ~dwc->mask; + if (!dw->in_use) + dw_dma_off(dw); + list_for_each_entry_safe(desc, _desc, &list, desc_node) { dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc); dma_pool_free(dw->desc_pool, desc, desc->txd.phys); @@ -1460,24 +1487,6 @@ EXPORT_SYMBOL(dw_dma_cyclic_free); /*----------------------------------------------------------------------*/ -static void dw_dma_off(struct dw_dma *dw) -{ - int i; - - dma_writel(dw, CFG, 0); - - channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); - channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask); - channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask); - channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); - - while (dma_readl(dw, CFG) & DW_CFG_DMA_EN) - cpu_relax(); - - for (i = 0; i < dw->dma.chancnt; i++) - dw->chan[i].initialized = false; -} - int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) { struct dw_dma *dw; @@ -1495,13 +1504,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dw->regs = chip->regs; chip->dw = dw; - dw->clk = devm_clk_get(chip->dev, "hclk"); - if (IS_ERR(dw->clk)) - return PTR_ERR(dw->clk); - err = clk_prepare_enable(dw->clk); - if (err) - return err; - dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); autocfg = dw_params >> DW_PARAMS_EN & 0x1; @@ -1604,7 +1606,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) channel_clear_bit(dw, CH_EN, dwc->mask); dwc->direction = DMA_TRANS_NONE; - dwc->request_line = ~0; /* Hardware configuration */ if (autocfg) { @@ -1659,8 +1660,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dw->dma.device_tx_status = dwc_tx_status; dw->dma.device_issue_pending = dwc_issue_pending; - dma_writel(dw, CFG, DW_CFG_DMA_EN); - err = dma_async_device_register(&dw->dma); if (err) goto err_dma_register; @@ -1673,7 +1672,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) err_dma_register: free_irq(chip->irq, dw); err_pdata: - clk_disable_unprepare(dw->clk); return err; } EXPORT_SYMBOL_GPL(dw_dma_probe); @@ -1695,46 +1693,27 @@ int dw_dma_remove(struct dw_dma_chip *chip) channel_clear_bit(dw, CH_EN, dwc->mask); } - clk_disable_unprepare(dw->clk); - return 0; } EXPORT_SYMBOL_GPL(dw_dma_remove); -void dw_dma_shutdown(struct dw_dma_chip *chip) -{ - struct dw_dma *dw = chip->dw; - - dw_dma_off(dw); - clk_disable_unprepare(dw->clk); -} -EXPORT_SYMBOL_GPL(dw_dma_shutdown); - -#ifdef CONFIG_PM_SLEEP - -int dw_dma_suspend(struct dw_dma_chip *chip) +int dw_dma_disable(struct dw_dma_chip *chip) { struct dw_dma *dw = chip->dw; dw_dma_off(dw); - clk_disable_unprepare(dw->clk); - return 0; } -EXPORT_SYMBOL_GPL(dw_dma_suspend); +EXPORT_SYMBOL_GPL(dw_dma_disable); -int dw_dma_resume(struct dw_dma_chip *chip) +int dw_dma_enable(struct dw_dma_chip *chip) { struct dw_dma *dw = chip->dw; - clk_prepare_enable(dw->clk); - dma_writel(dw, CFG, DW_CFG_DMA_EN); - + dw_dma_on(dw); return 0; } -EXPORT_SYMBOL_GPL(dw_dma_resume); - -#endif /* CONFIG_PM_SLEEP */ +EXPORT_SYMBOL_GPL(dw_dma_enable); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller core driver"); diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h index 32667f9e0dda..41439732ff6b 100644 --- a/drivers/dma/dw/internal.h +++ b/drivers/dma/dw/internal.h @@ -8,63 +8,16 @@ * published by the Free Software Foundation. */ -#ifndef _DW_DMAC_INTERNAL_H -#define _DW_DMAC_INTERNAL_H +#ifndef _DMA_DW_INTERNAL_H +#define _DMA_DW_INTERNAL_H -#include <linux/device.h> -#include <linux/dw_dmac.h> +#include <linux/dma/dw.h> #include "regs.h" -/** - * struct dw_dma_chip - representation of DesignWare DMA controller hardware - * @dev: struct device of the DMA controller - * @irq: irq line - * @regs: memory mapped I/O space - * @dw: struct dw_dma that is filed by dw_dma_probe() - */ -struct dw_dma_chip { - struct device *dev; - int irq; - void __iomem *regs; - struct dw_dma *dw; -}; - -/* Export to the platform drivers */ -int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata); -int dw_dma_remove(struct dw_dma_chip *chip); - -void dw_dma_shutdown(struct dw_dma_chip *chip); - -#ifdef CONFIG_PM_SLEEP - -int dw_dma_suspend(struct dw_dma_chip *chip); -int dw_dma_resume(struct dw_dma_chip *chip); - -#endif /* CONFIG_PM_SLEEP */ +int dw_dma_disable(struct dw_dma_chip *chip); +int dw_dma_enable(struct dw_dma_chip *chip); -/** - * dwc_get_dms - get destination master - * @slave: pointer to the custom slave configuration - * - * Returns destination master in the custom slave configuration if defined, or - * default value otherwise. - */ -static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave) -{ - return slave ? slave->dst_master : 0; -} - -/** - * dwc_get_sms - get source master - * @slave: pointer to the custom slave configuration - * - * Returns source master in the custom slave configuration if defined, or - * default value otherwise. - */ -static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave) -{ - return slave ? slave->src_master : 1; -} +extern bool dw_dma_filter(struct dma_chan *chan, void *param); -#endif /* _DW_DMAC_INTERNAL_H */ +#endif /* _DMA_DW_INTERNAL_H */ diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c index 39e30c3c7a9d..b144706b3d85 100644 --- a/drivers/dma/dw/pci.c +++ b/drivers/dma/dw/pci.c @@ -82,7 +82,7 @@ static int dw_pci_suspend_late(struct device *dev) struct pci_dev *pci = to_pci_dev(dev); struct dw_dma_chip *chip = pci_get_drvdata(pci); - return dw_dma_suspend(chip); + return dw_dma_disable(chip); }; static int dw_pci_resume_early(struct device *dev) @@ -90,7 +90,7 @@ static int dw_pci_resume_early(struct device *dev) struct pci_dev *pci = to_pci_dev(dev); struct dw_dma_chip *chip = pci_get_drvdata(pci); - return dw_dma_resume(chip); + return dw_dma_enable(chip); }; #endif /* CONFIG_PM_SLEEP */ @@ -108,6 +108,10 @@ static const struct pci_device_id dw_pci_id_table[] = { { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_pdata }, { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_pdata }, + /* Braswell */ + { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_pci_pdata }, + { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_pci_pdata }, + /* Haswell */ { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_pci_pdata }, { } diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index c5b339af6be5..a630161473a4 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -25,72 +25,49 @@ #include "internal.h" -struct dw_dma_of_filter_args { - struct dw_dma *dw; - unsigned int req; - unsigned int src; - unsigned int dst; -}; - -static bool dw_dma_of_filter(struct dma_chan *chan, void *param) -{ - struct dw_dma_chan *dwc = to_dw_dma_chan(chan); - struct dw_dma_of_filter_args *fargs = param; - - /* Ensure the device matches our channel */ - if (chan->device != &fargs->dw->dma) - return false; - - dwc->request_line = fargs->req; - dwc->src_master = fargs->src; - dwc->dst_master = fargs->dst; - - return true; -} - static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { struct dw_dma *dw = ofdma->of_dma_data; - struct dw_dma_of_filter_args fargs = { - .dw = dw, + struct dw_dma_slave slave = { + .dma_dev = dw->dma.dev, }; dma_cap_mask_t cap; if (dma_spec->args_count != 3) return NULL; - fargs.req = dma_spec->args[0]; - fargs.src = dma_spec->args[1]; - fargs.dst = dma_spec->args[2]; + slave.src_id = dma_spec->args[0]; + slave.dst_id = dma_spec->args[0]; + slave.src_master = dma_spec->args[1]; + slave.dst_master = dma_spec->args[2]; - if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS || - fargs.src >= dw->nr_masters || - fargs.dst >= dw->nr_masters)) + if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS || + slave.dst_id >= DW_DMA_MAX_NR_REQUESTS || + slave.src_master >= dw->nr_masters || + slave.dst_master >= dw->nr_masters)) return NULL; dma_cap_zero(cap); dma_cap_set(DMA_SLAVE, cap); /* TODO: there should be a simpler way to do this */ - return dma_request_channel(cap, dw_dma_of_filter, &fargs); + return dma_request_channel(cap, dw_dma_filter, &slave); } #ifdef CONFIG_ACPI static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) { - struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct acpi_dma_spec *dma_spec = param; + struct dw_dma_slave slave = { + .dma_dev = dma_spec->dev, + .src_id = dma_spec->slave_id, + .dst_id = dma_spec->slave_id, + .src_master = 1, + .dst_master = 0, + }; - if (chan->device->dev != dma_spec->dev || - chan->chan_id != dma_spec->chan_id) - return false; - - dwc->request_line = dma_spec->slave_id; - dwc->src_master = dwc_get_sms(NULL); - dwc->dst_master = dwc_get_dms(NULL); - - return true; + return dw_dma_filter(chan, &slave); } static void dw_dma_acpi_controller_register(struct dw_dma *dw) @@ -201,10 +178,17 @@ static int dw_probe(struct platform_device *pdev) chip->dev = dev; - err = dw_dma_probe(chip, pdata); + chip->clk = devm_clk_get(chip->dev, "hclk"); + if (IS_ERR(chip->clk)) + return PTR_ERR(chip->clk); + err = clk_prepare_enable(chip->clk); if (err) return err; + err = dw_dma_probe(chip, pdata); + if (err) + goto err_dw_dma_probe; + platform_set_drvdata(pdev, chip); if (pdev->dev.of_node) { @@ -219,6 +203,10 @@ static int dw_probe(struct platform_device *pdev) dw_dma_acpi_controller_register(chip->dw); return 0; + +err_dw_dma_probe: + clk_disable_unprepare(chip->clk); + return err; } static int dw_remove(struct platform_device *pdev) @@ -228,14 +216,18 @@ static int dw_remove(struct platform_device *pdev) if (pdev->dev.of_node) of_dma_controller_free(pdev->dev.of_node); - return dw_dma_remove(chip); + dw_dma_remove(chip); + clk_disable_unprepare(chip->clk); + + return 0; } static void dw_shutdown(struct platform_device *pdev) { struct dw_dma_chip *chip = platform_get_drvdata(pdev); - dw_dma_shutdown(chip); + dw_dma_disable(chip); + clk_disable_unprepare(chip->clk); } #ifdef CONFIG_OF @@ -261,7 +253,10 @@ static int dw_suspend_late(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct dw_dma_chip *chip = platform_get_drvdata(pdev); - return dw_dma_suspend(chip); + dw_dma_disable(chip); + clk_disable_unprepare(chip->clk); + + return 0; } static int dw_resume_early(struct device *dev) @@ -269,7 +264,8 @@ static int dw_resume_early(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct dw_dma_chip *chip = platform_get_drvdata(pdev); - return dw_dma_resume(chip); + clk_prepare_enable(chip->clk); + return dw_dma_enable(chip); } #endif /* CONFIG_PM_SLEEP */ @@ -281,7 +277,7 @@ static const struct dev_pm_ops dw_dev_pm_ops = { static struct platform_driver dw_driver = { .probe = dw_probe, .remove = dw_remove, - .shutdown = dw_shutdown, + .shutdown = dw_shutdown, .driver = { .name = "dw_dmac", .pm = &dw_dev_pm_ops, diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index bb98d3e91e8b..848e232f7cc7 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -11,7 +11,6 @@ #include <linux/interrupt.h> #include <linux/dmaengine.h> -#include <linux/dw_dmac.h> #define DW_DMA_MAX_NR_CHANNELS 8 #define DW_DMA_MAX_NR_REQUESTS 16 @@ -132,6 +131,18 @@ struct dw_dma_regs { /* Bitfields in DWC_PARAMS */ #define DWC_PARAMS_MBLK_EN 11 /* multi block transfer */ +/* bursts size */ +enum dw_dma_msize { + DW_DMA_MSIZE_1, + DW_DMA_MSIZE_4, + DW_DMA_MSIZE_8, + DW_DMA_MSIZE_16, + DW_DMA_MSIZE_32, + DW_DMA_MSIZE_64, + DW_DMA_MSIZE_128, + DW_DMA_MSIZE_256, +}; + /* Bitfields in CTL_LO */ #define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ #define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ @@ -161,20 +172,35 @@ struct dw_dma_regs { #define DWC_CTLH_DONE 0x00001000 #define DWC_CTLH_BLOCK_TS_MASK 0x00000fff -/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/dw_dmac.h> */ +/* Bitfields in CFG_LO */ #define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */ #define DWC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */ #define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ #define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ #define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ #define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */ +#define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */ +#define DWC_CFGL_LOCK_CH_BLOCK (1 << 12) +#define DWC_CFGL_LOCK_CH_XACT (2 << 12) +#define DWC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */ +#define DWC_CFGL_LOCK_BUS_BLOCK (1 << 14) +#define DWC_CFGL_LOCK_BUS_XACT (2 << 14) +#define DWC_CFGL_LOCK_CH (1 << 15) /* channel lockout */ +#define DWC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */ +#define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ +#define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ #define DWC_CFGL_MAX_BURST(x) ((x) << 20) #define DWC_CFGL_RELOAD_SAR (1 << 30) #define DWC_CFGL_RELOAD_DAR (1 << 31) -/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/dw_dmac.h> */ +/* Bitfields in CFG_HI */ +#define DWC_CFGH_FCMODE (1 << 0) +#define DWC_CFGH_FIFO_MODE (1 << 1) +#define DWC_CFGH_PROTCTL(x) ((x) << 2) #define DWC_CFGH_DS_UPD_EN (1 << 5) #define DWC_CFGH_SS_UPD_EN (1 << 6) +#define DWC_CFGH_SRC_PER(x) ((x) << 7) +#define DWC_CFGH_DST_PER(x) ((x) << 11) /* Bitfields in SGR */ #define DWC_SGR_SGI(x) ((x) << 0) @@ -221,9 +247,10 @@ struct dw_dma_chan { bool nollp; /* custom slave configuration */ - unsigned int request_line; - unsigned char src_master; - unsigned char dst_master; + u8 src_id; + u8 dst_id; + u8 src_master; + u8 dst_master; /* configuration passed via DMA_SLAVE_CONFIG */ struct dma_slave_config dma_sconfig; @@ -250,11 +277,11 @@ struct dw_dma { void __iomem *regs; struct dma_pool *desc_pool; struct tasklet_struct tasklet; - struct clk *clk; /* channels */ struct dw_dma_chan *chan; u8 all_chan_mask; + u8 in_use; /* hardware configuration */ unsigned char nr_masters; |